package com.topisv.tms.service.work;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.hibernate.ejb.criteria.predicate.ComparisonPredicate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.topisv.tms.entity.AreaGroup;
import com.topisv.tms.entity.Customers;
import com.topisv.tms.entity.EdiOrder;
import com.topisv.tms.entity.EdiOrderItem;
import com.topisv.tms.entity.LogisticsCompany;
import com.topisv.tms.entity.QueryParamHolder;
import com.topisv.tms.entity.User;
import com.topisv.tms.entity.interfacetask.InterfaceTask;
import com.topisv.tms.entity.interfacetask.InterfaceTaskEnum;
import com.topisv.tms.entity.log.OrderLog;
import com.topisv.tms.entity.stock.CusStock;
import com.topisv.tms.entity.stock.instorage.OutstorageInfo;
import com.topisv.tms.entity.work.WholePileConfig;
import com.topisv.tms.entity.work.WorkBatch;
import com.topisv.tms.entity.work.WorkLog;
import com.topisv.tms.entity.work.WorkOrder;
import com.topisv.tms.entity.work.WorkTask;
import com.topisv.tms.entity.work.WorkTaskItem;
import com.topisv.tms.entity.work.ExceptionOrder.ExceptionOrder;
import com.topisv.tms.entity.workBox.WorkBox;
import com.topisv.tms.exception.ErrorCode;
import com.topisv.tms.exception.PaiUException;
import com.topisv.tms.repository.AreaGroupDao;
import com.topisv.tms.repository.CustomersDao;
import com.topisv.tms.repository.EdiOrderItemDao;
import com.topisv.tms.repository.LogisticsCompanyDao;
import com.topisv.tms.repository.UserDao;
import com.topisv.tms.repository.log.OrderLogDao;
import com.topisv.tms.repository.stock.CusStockDao;
import com.topisv.tms.repository.work.WholePileConfigDao;
import com.topisv.tms.repository.work.WorkBatchDao;
import com.topisv.tms.repository.work.WorkLogDao;
import com.topisv.tms.repository.work.WorkOrderDao;
import com.topisv.tms.repository.work.WorkTaskDao;
import com.topisv.tms.repository.work.WorkTaskItemDao;
import com.topisv.tms.repository.work.ExceptionOrder.ExceptionOrderDao;
import com.topisv.tms.repository.workBox.WorkBoxDao;
import com.topisv.tms.rest.qimen.qmsend.QmRequestSender;
import com.topisv.tms.rest.qimen.qmservice.DeliveryProcessService;
import com.topisv.tms.rest.qimen.qmservice.OrderOutofstockService;
import com.topisv.tms.service.CusStockMergeService;
import com.topisv.tms.service.EdiOrderService;
import com.topisv.tms.service.WorkGuaranteeTaskService;
import com.topisv.tms.service.account.ShiroDbRealm.ShiroUser;
import com.topisv.tms.service.base.BaseService;
import com.topisv.tms.service.interfacetask.InterfaceTaskService;
import com.topisv.tms.service.pickCar.PickCarService;
import com.topisv.tms.service.stock.CusStockService;
import com.topisv.tms.service.stock.instorage.OutstorageInfoService;
import com.topisv.tms.tools.TransferHelper;

/**
 * 作业批次_service
 * 
 * @author ch
 * 
 */
@Component
@Transactional(readOnly = true)
public class WorkTaskService extends BaseService{

    private static final Logger log = LoggerFactory.getLogger(WorkTaskService.class);
    
    @Autowired
    private EdiOrderItemDao ediOrderItemDao;
    
    @Autowired
    private CusStockDao cusStockDao;
    @Autowired
    private WorkBatchDao workBatchDao;
    @Autowired
    private WorkOrderDao workOrderDao;
    @Autowired
    private WorkBatchService workBatchService;
    @Autowired
    private UserDao userDao;
    @Autowired
    private WorkTaskDao workTaskDao;
    @Autowired
    private WorkBoxDao workBoxDao;
    @Autowired
    private OrderLogDao orderLogDao;
    @Autowired
    private WorkLogDao workLogDao;
    @Autowired
    private EdiOrderService ediOrderService;
    @Autowired
    private WorkTaskItemDao workTaskItemDao;
    @Autowired
    private CustomersDao customersDao;
    @Autowired
    private AreaGroupDao areaGroupDao;
    @Autowired
    private OutstorageInfoService outstorageInfoService;
    @Autowired
    private CusStockMergeService cusStockMergeService;
    @Autowired
    private LogisticsCompanyDao  logisticsCompanyDao;
    @Autowired
    private ExceptionOrderDao  exceptionOrderDao;
    @Resource(type=DeliveryProcessService.class)
    private QmRequestSender<Map<String,Object>> deliveryProcessService;
    @Autowired
    private WholePileConfigDao wpcDao;
    @Autowired
    private WorkGuaranteeTaskService workGuaranteeTaskService;
    @Autowired
    private PickCarService pickCarService;
   @Autowired
    private InterfaceTaskService interfaceTaskService;
   @Autowired
   private CusStockService cusStockService;
   @PersistenceContext
   private EntityManager em;
   
    /**
     * 修改随箱单标识
     * @param workIds
     */
    @Transactional(readOnly = false)
    public void updatePackFormStatus(String workIds){
        String[] workIdLists=workIds.split(":");
		for (String id : workIdLists) {
			WorkTask w = workTaskDao.findOne(Long.parseLong(id));

			// 修改随箱单的打印状态 bug554 by zhangweize 2016-10-31
			setPrintStatus(w);

		}
    }
    
  
    
    /**
     * 
     * 
     * 修改随箱单标识
     * @param taskCodes [参数说明]
     * @author <a href=mailto:zhangweize@nryuncang.com>zhangweize</a>
     * @version 1.0.0
     */
    @Transactional(readOnly = false)
    public void updatePackFormStatus(List<String> taskCodeList){
        
		for (String taskCode : taskCodeList) {
			WorkTask w = workTaskDao.loadTaskByTaskCode(taskCode);
			setPrintStatus(w);
		}
    }
    
    /**
     * 打印随箱单时修改状态
     * @param workTask
     */
    @Transactional(readOnly = false)
    public void setPrintStatus(WorkTask workTask) {
      //设置任务状态未已打印
        String printStatus = workTask.getPrintStatus();
       if("yes".equals(workTask.getExpressStatus())){
            //workTask.setPrintStatus("printed");
           printStatus = "printed";
        }
       workTaskDao.updatePackPrintStatus("yes", printStatus, workTask.getTaskCode());
    
    }
    
    
    /**
     * 创建任务_单件
     * @param orderList 待处理订单
     * @param workBatch 任务批次
     * @param tactics 任务策略 SKU(SKU集中策略) path(路径优化策略) singleSKU(单品合拣策略) wholeBox(整箱分拣策略)
     * @param taskcount 任务容量
     * @return
     * @throws Exception
     */
    public List<WorkTask> createTask_single(List<WorkOrder> orderList, WorkBatch workBatch, String tactics, Integer taskcount) throws Exception {
        
        try {

            List<WorkTask> taskList = new ArrayList<WorkTask>();
            List<WorkOrder> tempOrderList = new ArrayList<WorkOrder>();

            //加载订单明细
            for (int i = 0; i < orderList.size(); i++) {
                WorkOrder o = orderList.get(i);
                List<EdiOrderItem> orderItems = this.ediOrderItemDao.findByOrdeno(o.getOrder().getOrdeno());
                o.getOrder().setOrderItems(orderItems);
            }
            //整托拣选
            if(tactics.equals("wholePile")){
                //获取整托配置
                List<WholePileConfig> wpcList = wpcDao.findAll();
                Map<String ,WholePileConfig> wpcMap = new HashMap<String,WholePileConfig>();
                for(WholePileConfig wpc:wpcList){
                    String key = wpc.getCustomerCode()+":"+wpc.getWarehouseCode()+":"+wpc.getSku();
                    wpcMap.put(key,wpc);
                }
                
                //sku排序—按sku需求量
                Map<String, List<List<WorkOrder>>> keyMap = new HashMap<String, List<List<WorkOrder>>>();
                for (WorkOrder o : orderList) {
                    String sku = o.getOrder().getOrderItems().get(0).getSku();
                    String warehouseCode = o.getWarehouseCode();
                    String customerCode = o.getCustomerCode();
                    String key = customerCode +":"+warehouseCode+":"+sku;
                    WholePileConfig wpc = wpcMap.get(key);
                    if(wpc == null){
                        continue;
                    }
                    
                    if (keyMap.containsKey(key)) {
                        List<List<WorkOrder>> keyList = keyMap.get(key);
                        
                        if(keyList.get(keyList.size()-1).size()<wpc.getWholePileQty()){
                            keyList.get(keyList.size()-1).add(o);
                        }else {
                            List<WorkOrder> woList = new ArrayList<WorkOrder>();
                            woList.add(o);
                            keyList.add(woList);
                        }
                    } else {
                        List<List<WorkOrder>> keyList = new ArrayList<List<WorkOrder>>();
                        List<WorkOrder> woList = new ArrayList<WorkOrder>();
                        woList.add(o);
                        keyList.add(woList);
                        keyMap.put(key, keyList);
                    }
                }
                this.setWholePileBoxCode(keyMap, workBatch.getCustomerCode(),workBatch.getWarehouseCode(),tactics);
                
                WorkTask task = null;
                for(Entry<String, List<List<WorkOrder>>> keyMapItem : keyMap.entrySet()) {
                    String key = keyMapItem.getKey();
                    List<List<WorkOrder>> keyList = keyMapItem.getValue();
                    WholePileConfig wpc = wpcMap.get(key);
                    for(List<WorkOrder> woList : keyList){
                        if(woList.size()<=wpc.getWholePileQty()){
                            
                            
                            task = new WorkTask();
                            task.setBatchCode(workBatch.getBatchCode());
                            task.setCustomerCode(workBatch.getCustomerCode());
                            task.setOrderQty(workBatch.getOrderQty());
                            task.setPickType("single");
                            task.setBillType(workBatch.getBillType());
                            task.setFlowType(workBatch.getFlowType());
                            task.setOrderList(new ArrayList<WorkOrder>());
                            
                            for(WorkOrder wo:woList){
                                //设置是否满足库存属性
                                this.checkStock(wo);
                                
                                if("prepkg".equals(tactics) && "no".equals(wo.getStockCheck()) ){ //如果是预包装策略，且没有包装好的库存可以拣货，取消这单
                                }else{
                                    task.getOrderList().add(wo);
                                }
                                
                            }
                            taskList.add(task);
                        }
                    }
                }
                
                
                //设置rankno
                for (WorkTask _task : taskList) {
                    List<WorkOrder> _orderList=_task.getOrderList();
                    
                    Collections.sort(_orderList,
                        new Comparator<WorkOrder>() {
                            public int compare(
                                    WorkOrder order1,
                                    WorkOrder order2) {
                                String stockInfo_1=order1.getStockInfo()==null?"":order1.getStockInfo();
                                String stockInfo_2=order2.getStockInfo()==null?"":order2.getStockInfo();
                                return stockInfo_1.compareTo(stockInfo_2);
                            }
                    });
                    int rankno=0;
                    for (WorkOrder workOrder : _orderList) {
                        workOrder.setRankno(++rankno);
                    }
                }
                
                
            }else {
                //sku排序—按sku需求量
                Map<String, Integer> skuMap = new HashMap<String, Integer>();
                for (WorkOrder o : orderList) {
                    String sku = o.getOrder().getOrderItems().get(0).getSku();
                    if (skuMap.containsKey(sku)) {
                        skuMap.put(sku, skuMap.get(sku) + 1);
                    } else {
                        skuMap.put(sku, 1);
                    }
                }
                List<Map.Entry<String, Integer>> mappingList = new ArrayList<Map.Entry<String, Integer>>(skuMap.entrySet());
                Collections.sort(mappingList,
                        new Comparator<Map.Entry<String, Integer>>() {
                            public int compare(
                                    Map.Entry<String, Integer> mapping1,
                                    Map.Entry<String, Integer> mapping2) {
                                return -mapping1.getValue().compareTo(mapping2.getValue());
                            }
                });
                for (Map.Entry<String, Integer> mapping : mappingList) {
                    String sku = mapping.getKey();
                    for (WorkOrder order : orderList) {
                        if (order.getOrder().getOrderItems().get(0).getSku().equals(sku)) {
                            tempOrderList.add(order);
                        }
                    }
                }
                // 设置拣货库位、箱位
                this.setBoxCode_single(tempOrderList, workBatch.getCustomerCode(),workBatch.getWarehouseCode(),tactics);
                
                
                
                // 分隔订单-按任务容量
                WorkTask task = null;
                for (int i = 0; i < tempOrderList.size(); i++) {
                    WorkOrder order = tempOrderList.get(i);
                    
                    //设置是否满足库存属性
                    this.checkStock(order);
                    
                    if (i % taskcount == 0) {
                        task = new WorkTask();
                        task.setBatchCode(workBatch.getBatchCode());
                        task.setCustomerCode(workBatch.getCustomerCode());
                        task.setOrderQty(workBatch.getOrderQty());
                        task.setPickType("single");
                        task.setBillType(workBatch.getBillType());
                        task.setFlowType(workBatch.getFlowType());
                        task.setOrderList(new ArrayList<WorkOrder>());
                        taskList.add(task);
                    }
                    
                    if("prepkg".equals(tactics) && "no".equals(order.getStockCheck()) ){ //如果是预包装策略，且没有包装好的库存可以拣货，取消这单
                    }else{
                        task.getOrderList().add(order);
                    }
                    
                    
                }
                
                //设置rankno
                for (WorkTask _task : taskList) {
                    List<WorkOrder> _orderList=_task.getOrderList();
                    
                    Collections.sort(_orderList,
                        new Comparator<WorkOrder>() {
                            public int compare(
                                    WorkOrder order1,
                                    WorkOrder order2) {
                                String stockInfo_1=order1.getStockInfo()==null?"":order1.getStockInfo();
                                String stockInfo_2=order2.getStockInfo()==null?"":order2.getStockInfo();
                                return stockInfo_1.compareTo(stockInfo_2);
                            }
                    });
                    int rankno=0;
                    for (WorkOrder workOrder : _orderList) {
                        workOrder.setRankno(++rankno);
                    }
                }
                
                
            }
                
            
            
            

            
            
            
            return taskList;

        } catch (Exception e) {
            
            throw e;
        }

    }
    
    
    /**
     * 创建任务_多件
     * @param orderList 待处理订单
     * @param workBatch 任务批次
     * @param tactics 任务策略 SKU(SKU集中策略) path(路径优化策略) singleSKU(单品合拣策略) wholeBox(整箱分拣策略) batchsku(大促策略)
     * @param taskcount 任务容量
     * @return
     * @throws Exception
     */
    public Map<Object,Object> createTask_multi(List<WorkOrder> orderList,WorkBatch workBatch, String tactics, Integer taskcount) throws Exception {
        try {

            List<WorkTask> taskList = new ArrayList<WorkTask>();
            List<WorkOrder> tempOrderList = new ArrayList<WorkOrder>();
            tempOrderList=orderList;

            for (int i = 0; i < orderList.size(); i++) {
                WorkOrder o = orderList.get(i);
                List<EdiOrderItem> orderItems = this.ediOrderItemDao.findByOrdeno(o.getOrder().getOrdeno());
                o.getOrder().setOrderItems(orderItems);
            }

            // 设置拣货库位、箱位
            String skuList = this.setBoxCode_multi(tempOrderList, workBatch.getCustomerCode(),workBatch.getWarehouseCode());
            
            
            // 分隔订单-按任务容量
            WorkTask task = null;
            for (int i = 0; i < tempOrderList.size(); i++) {
                WorkOrder order = tempOrderList.get(i);
                
                //设置是否满足库存属性
                this.checkStock(order);
                
                if (i % taskcount == 0) {
                    task = new WorkTask();
                    task.setBatchCode(workBatch.getBatchCode());
                    task.setCustomerCode(workBatch.getCustomerCode());
                    task.setOrderQty(workBatch.getOrderQty());
                    task.setPickType("multi"); //任务类型 (single: 单件 multi: 多件)
                    task.setBillType(workBatch.getBillType());
                    task.setFlowType(workBatch.getFlowType());
                    task.setOrderList(new ArrayList<WorkOrder>());
                    taskList.add(task);
                }
                task.getOrderList().add(order);
            }
            
            //set rankno
            for (WorkTask _task : taskList) {
                List<WorkOrder> _orderList=_task.getOrderList();
                
                Collections.sort(_orderList,
                    new Comparator<WorkOrder>() {
                        public int compare(
                                WorkOrder order1,
                                WorkOrder order2) {
                            String stockInfo_1=order1.getStockInfo()==null?"":order1.getStockInfo();
                            String stockInfo_2=order2.getStockInfo()==null?"":order2.getStockInfo();
                            return stockInfo_1.compareTo(stockInfo_2);
                        }
                });
                
                int rankno=0;
                for (WorkOrder workOrder : _orderList) {
                    workOrder.setRankno(++rankno);
                }
            }
            Map<Object, Object> map = new HashMap<Object, Object>();
            map.put("workList", taskList);
            map.put("skuList", skuList);
            return map;

        } catch (Exception e) {
            
            throw e;
        }

    }
    
    /**
     * 设置是否满足库存属性
     * @param taskList
     */
    private void checkStock(WorkOrder _order){
            
        String stockInfo=_order.getStockInfo();
        if(StringUtils.isBlank(stockInfo)){
            _order.setStockCheck("no");
        }else{
            List<EdiOrderItem> _itemList=this.ediOrderItemDao.findByOrdeno(_order.getOrder().getOrdeno());
            int totalNum_1=0;
            for (EdiOrderItem _item : _itemList) {
                totalNum_1+=_item.getQty();
            }
            
            String[] _infoSplit=stockInfo.split(";");
            int totalNum_2=0;
            for (String _info : _infoSplit) {
                String[] _split=_info.split("_");
                totalNum_2+=Integer.valueOf(_split[3]);
            }
            
            if(totalNum_1!=totalNum_2){
                _order.setStockCheck("no");
            }
        }
    }
    public static void main(String[] args) {
        List<CusStock> stockList = new ArrayList<CusStock>();
        CusStock c = new CusStock();
        c.setSalesNum(7);
        c.setStockCode("A002");
        stockList.add(c);
        
        c = new CusStock();
        c.setSalesNum(2);
        c.setStockCode("A000");
        stockList.add(c);
        
        c = new CusStock();
        c.setSalesNum(33);
        c.setStockCode("A000");
        stockList.add(c);
        
        
        c = new CusStock();
        c.setSalesNum(20);
        c.setStockCode("A001");
        stockList.add(c);
        
        c = new CusStock();
        c.setSalesNum(5);
        c.setStockCode("A003");
        stockList.add(c);


        showList(stockList);
        System.out.println("=================================");
        stockList = cusStockOrderBy(stockList, 5);
        showList(stockList);
    }
    public static void showList(List<CusStock> stockList){
        for(CusStock cus:stockList){
            System.out.println(cus.getSalesNum()+"|"+cus.getStockCode());
        }
    }
    public static List<CusStock> cusStockOrderBy(List<CusStock> stockList,int needNum){
        List<CusStock> stockTempList = new ArrayList<CusStock>();
        // 库位升序，
//      Collections.sort(stockList, new Comparator<CusStock>() {
//          public int compare(CusStock o1, CusStock o2) {
//              return o1.getStockCode().compareTo(o2.getStockCode());
//          }
//      });
        
        Map<String,List<CusStock>> boxMap = new HashMap<String,List<CusStock>>();
        for(CusStock cus:stockList){
            if(boxMap.containsKey(cus.getStockCode())){
                boxMap.get(cus.getStockCode()).add(cus);
            }else {
                List<CusStock> sortSalesNum = new ArrayList<CusStock>();
                sortSalesNum.add(cus);
                boxMap.put(cus.getStockCode(), sortSalesNum);
            }
        }
        
         List<String> keyList = new ArrayList<String>(boxMap.keySet());
        Collections.sort(keyList,new Comparator<String>() {
             public int compare(String a,String b) {
                return  a.compareTo(b);
             }
        }); 
        
        for(String key : keyList) {
            List<CusStock> cl = (List<CusStock>)boxMap.get(key);
//          // 库位升序，
            Collections.sort(cl, new Comparator<CusStock>() {
                public int compare(CusStock o1, CusStock o2) {
                    return o2.getSalesNum().compareTo(o1.getSalesNum());
                }
            });
            stockTempList.addAll(cl);
        }
        stockList = stockTempList;

        
        stockTempList = new ArrayList<CusStock>();
        
        //将比需要数量多的提前
        for(int q = stockList.size() - 1; q >= 0 ;q--){
            CusStock cus = stockList.get(q);
            if(cus.getSalesNum() > needNum){
                stockTempList.add(0,cus);
                stockList.remove(cus);
            }
        }
        //将数量与需求数量一致的提到最前面
        for(int q = stockList.size() - 1; q >= 0;q--){
            CusStock cus = stockList.get(q);
            if(cus.getSalesNum() == needNum){
                stockTempList.add(0,cus);
                stockList.remove(cus);
            }
        }
        stockTempList.addAll(stockList);
        
        stockList = stockTempList;
        return stockList;
    }
    /**
     * 设置最接近任务数量库位、箱位_单件
     * @param workOrderList  作业订单集合
     * @param customerCode 商户编码
     * @param warehouseCode 仓库编码
     * @param tactics 拣货策略
     * @return errorList 库存不足的sku序列（多个以逗号间隔）
     * @throws Exception 
     */
    private String setWholePileBoxCode(Map<String, List<List<WorkOrder>>> keyMap, String customerCode,String warehouseCode,String tactics) throws Exception {
        List<CusStock> stockList=null;
        
        for(Entry<String, List<List<WorkOrder>>> keyMapItem : keyMap.entrySet()) {
            String key = keyMapItem.getKey();
            String sku = key.split(":")[2];
            List<List<WorkOrder>> keyList = keyMapItem.getValue();
            stockList = this.cusStockDao.loadStockOrderByStockCodeAndSalesNum(warehouseCode, customerCode, sku);
            
            for(final List<WorkOrder> woList : keyList){
                int sku_num = woList.size();
                
                stockList = cusStockOrderBy(stockList, sku_num);
                // 找到最接近满足的箱位
                for (CusStock cusStock : stockList) {
//                  if (cusStock.getSalesNum() >= sku_num) {
                        for (WorkOrder pOrder : woList) {
                            if(cusStock.getSalesNum()>=1){
                                String _sku = pOrder.getOrder().getOrderItems().get(0).getSku();
                                String _stockInfo = pOrder.getStockInfo();
                                if (_sku.equals(sku) && StringUtils.isEmpty(_stockInfo)) {
                                    pOrder.setStockInfo(cusStock.getStockCode() + "_"+ cusStock.getBoxCode() + "_" + _sku + "_"+ 1 + ";");
                                    //订单所需数量减少
                                    sku_num--;
                                    //库存数量减少
                                    cusStock.setSalesNum(cusStock.getSalesNum()-1);
                                }
                            }
                        }
                        //如果改任务所有需求的订单需要的sku数量为0则不需要找库存
                        if(sku_num == 0){
                            break;
                        }
//                  }
                }
                
            }
        }
        return "";
    }
    
    /**
     * 设置库位、箱位_单件
     * @param workOrderList  作业订单集合
     * @param customerCode 商户编码
     * @param warehouseCode 仓库编码
     * @param tactics 拣货策略
     * @return errorList 库存不足的sku序列（多个以逗号间隔）
     * @throws Exception 
     */
    private String setBoxCode_single(List<WorkOrder> workOrderList, String customerCode,String warehouseCode,String tactics) throws Exception {

        String errorList="";
        
        // sku数量分类
        Map<String, Integer> skuMap = new HashMap<String, Integer>();
        for (WorkOrder o : workOrderList) {
            String sku = o.getOrder().getOrderItems().get(0).getSku();
            if (skuMap.containsKey(sku)) {
                skuMap.put(sku, skuMap.get(sku) + 1);
            } else {
                skuMap.put(sku, 1);
            }
        }

        // 给每个sku分配库存
        for (String sku : skuMap.keySet()) {
            
            int sku_num = skuMap.get(sku); // 每个sku需求数量.
            
            List<CusStock> stockList=null;
            if("prepkg".equals(tactics)){ //如果是预包装，只能拣prepkg类型的库存
                stockList = this.cusStockDao.loadStock(customerCode, warehouseCode, sku, "prepkg"); 
            }else{
                stockList = this.cusStockDao.loadStockOrderByStockCodeAndSalesNum(warehouseCode, customerCode, sku);
            }

            // 如果没有找到最接近的箱位，箱位组合分配。
            for (CusStock cusStock : stockList) {
               
                if (sku_num == 0){
                    break;
                }
                
                if(cusStock.getSalesNum()<=0){
                    continue;
                }
                
                for (WorkOrder pOrder : workOrderList) {
                    String _sku = pOrder.getOrder().getOrderItems().get(0).getSku();
                    String _stockInfo = pOrder.getStockInfo();
                    if (_sku.equals(sku) && StringUtils.isBlank(_stockInfo)) {
                        pOrder.setStockInfo(cusStock.getStockCode() + "_" + cusStock.getBoxCode() + "_" + _sku + "_" + 1 + ";");
                        sku_num--;
                        cusStock.setSalesNum(cusStock.getSalesNum()-1);
                        
                        if(cusStock.getSalesNum()==0){
                            break;
                        }
                        
                    }
                }
                
            }
                
            
            if(sku_num>0){
                if(errorList.length()>0){
                    errorList+=",";
                }
                errorList+=sku;
            }
        }
        
        return errorList;
    }
    
    
    
    /**
     * 设置库位、箱位——多件
     * @param workOrderList  作业订单集合
     * @param customerCode 商户编码
     * @param warehouseCode 仓库编码
     * @return
     */
    private String setBoxCode_multi(List<WorkOrder> workOrderList, String customerCode,String warehouseCode) {
       
        String errorList="";
        
        for(WorkOrder o:workOrderList){
            Map<String, Integer> skuMap = new HashMap<String, Integer>();
            List<EdiOrderItem>  eOrderList = o.getOrder().getOrderItems();
            for(EdiOrderItem ediOrderItem : eOrderList){
                String sku = ediOrderItem.getSku();
                Integer num=ediOrderItem.getQty();
                if (skuMap.containsKey(sku)) {
                    skuMap.put(sku,skuMap.get(sku) + num);
                } else {
                    skuMap.put(sku, num);
                }
            }

            for(String sku : skuMap.keySet()){
                int sku_num = skuMap.get(sku); // 每个sku需求数量.
                List<CusStock> stockList = this.cusStockDao.loadStockOrderByStockCodeAndSalesNum(warehouseCode, customerCode, sku);
                
                // 如果没有找到最接近的箱位，箱位组合分配。
                for (CusStock cusStock : stockList) {
                    sku_num = this.setBoxCode(cusStock,o,sku_num);
                    
                    if(sku_num <= 0)
                        break;
                    
                }
                
                if(sku_num>0){
                    if(errorList.length()>0){
                        errorList+=",";
                    }
                    errorList+=sku;
                }
            }
                
        }
        return errorList;
    }
    
    public int setBoxCode(CusStock cusStock,WorkOrder workOrder,int sku_num){
        
            int needNum = sku_num;
            int stockNum = cusStock.getSalesNum();
            String _stockInfo = "";
            
            if(stockNum <= 0){
            }else{
                if(stockNum>=needNum){
                        cusStock.setSalesNum(stockNum-needNum);
                        _stockInfo=cusStock.getStockCode()+"_"+cusStock.getBoxCode()+"_"+cusStock.getSku()+"_"+needNum+";";
                        sku_num = 0;
                    }else{
                        cusStock.setSalesNum(0);
                        _stockInfo=cusStock.getStockCode()+"_"+cusStock.getBoxCode()+"_"+cusStock.getSku()+"_"+stockNum+";";
                        sku_num = sku_num - stockNum;
                        //flag=false;
                    }
                workOrder.setStockInfo(new StringBuilder().append(workOrder.getStockInfo()==null?"":workOrder.getStockInfo()).append(_stockInfo).toString());
            }
            return sku_num;
            
        }
    
    /**
     * 库位信息转化: String->map形式
     * @param stockInfo
     * @return
     */
    private Map<String, Integer>  stockInfo2Map(String stockInfo) {
        Map<String, Integer> map=new HashMap<String, Integer>();
        if(StringUtils.isBlank(stockInfo)){
            return map;
        }
        String[] stockInfoArray=stockInfo.split(";");
        for (String  info : stockInfoArray) {
            if(StringUtils.isNotBlank(info)){
                String[] _info=info.split("_");
                String sku=_info[2];
                Integer num=Integer.valueOf(_info[3]);
                if(map.keySet().contains(sku)){
                    map.put(sku,map.get(sku)+num);
                }else{
                    map.put(sku, num);  
                }
            }
        }
        
       return map;      
    }

    /**
     * 创建作业任务
     * @param stockMap 库位信息
     * @param batchCode  批次号
     * @return
     * @throws Exception
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public boolean createTask(Map<String, String> stockMap, Map<String, Integer> ranknoMap, String batchCode, String pickModel)  throws Exception {
        try {
            
            Date now = new Date();
            
            WorkBatch batch = this.workBatchDao.loadbatchByBatchCode(batchCode);
            String warehouseCode = batch.getWarehouseCode();
            String customerCode = batch.getCustomerCode();
            String billType = batch.getBillType();
            String flowType = batch.getFlowType();
            // 优先派送
            String psFlag = batch.getPrioritySendFlag();
            
            // 创建作业任务
            WorkTask task = new WorkTask();
            task.setBillType(billType);
            task.setFlowType(flowType);
            task.setBatchCode(batchCode);
            task.setPrintStatus("unprinted"); // 是否打印 （printed: 已打印 未打印：unprinted）
            task.setCustomerCode(customerCode);
            task.setCompanyCode(batch.getCompanyCode());
            task.setPickType(batch.getPickType());
            task.setStatus("1"); // 任务状态( 1.创建任务 2.已分配拣货任务 3.已拣货 4. 已分配灯光拣选任务 5.已经灯光拣选 6.已分配包装任务 7.已包装 8.已分配发货任务 9.已发货 10.灯光拣选进行中.. 11.推车拣选进行中.. 12.拣货中...)
            task.setWarehouseCode(warehouseCode);
            task.setBatchType(batch.getBatchType());
            task.setCreateTime(now);
            task.setOrderQty(stockMap.size());
            task.setPickModel(("promotion".equals(batch.getTacticsType()) || "comb".equals(batch.getTacticsType())) ? "normal" : pickModel);
            task.setGoodsNum(0l);
            task.setPickedNum(0l);
            // 优先派送
            task.setPrioritySendFlag(psFlag);
            
            task.setTacticsType(batch.getTacticsType());
            
            ShiroUser curUser = (ShiroUser)SecurityUtils.getSubject().getPrincipal();
            task.setCreaterId(curUser.id);
            this.workTaskDao.save(task);
            
            User user = this.userDao.findOne(curUser.id);
            
            DecimalFormat df = new DecimalFormat("000000");
            Long id = task.getId();
            String _taskCode = "T" + task.getCustomerCode() + df.format(id);
            task.setTaskCode(_taskCode);
            this.workTaskDao.save(task);
            
            String taskCode = task.getTaskCode();
            
            // 设置作业任务中的订单信息
            String stockInfo = null;
            for (String ordeno : stockMap.keySet()) {
                
                WorkOrder pOrder = this.workOrderDao.loadOrder(batchCode, ordeno);
                String taskCode_check = pOrder.getTaskCode();
                if (StringUtils.isNotBlank(taskCode_check)) {
                    throw new RuntimeException("重复创建任务，订单号：" + pOrder.getOrder().getOrdeno());
                }
                
                stockInfo = stockMap.get(ordeno);
                String[] infoArray = stockInfo.split(";");
                for (String info : infoArray) {
                    String[] _arr = info.split("_");
                    String stockCode = _arr[0];
                    String boxCode = _arr[1];
                    String sku = _arr[2];
                    Integer num = Integer.valueOf(_arr[3] + "");
                    
                    //修改库存信息
                    /*CusStock cusStock=this.cusStockDao.loadStock(customerCode,warehouseCode,stockCode,boxCode,sku);
                    if(cusStock.getSalesNum() - num < 0){
                        throw new Exception("库存不能满足，订单号："+ordeno+"  sku:"+sku);
                    }
                    cusStock.setSalesNum(cusStock.getSalesNum()-num);
                    cusStock.setOrderNum(cusStock.getOrderNum()+num);
                    this.cusStockDao.save(cusStock);*/

                    /** begin modify 20160920 采用单独的事务进行库存更新 */
                    try {
                        this.cusStockService.updateCusStock4CreateTask(customerCode, warehouseCode, batchCode, ordeno, stockCode, boxCode, sku, num);
                    } catch (Exception ex) {
                        log.error("更新库存失败，订单号：{}", ordeno, ex);
                        throw new RuntimeException("库存更新失败，订单号：" + ordeno + "  sku:" + sku);
                    }
                    /** end modify 20160920 采用单独的事务进行库存更新 */
                }

                //修改作业订单信息
                pOrder.setStatus("2"); // 订单状态 (1.创建作业批次 2.创建作业任务 3.已作业 4.已包装 5.已发货 6.已签收 7.异常登记)
                pOrder.setStockInfo(stockInfo);
                pOrder.setTaskCode(taskCode);
                pOrder.setRankno(ranknoMap.get(ordeno));
                this.workOrderDao.save(pOrder);
                
                task.setGoodsNum(task.getGoodsNum() + pOrder.getGoodsNum());
                if (TransferHelper.string2Boolean(pOrder.getNeedInvoice())) {
                    task.setNeedInvoice(pOrder.getNeedInvoice());
                    task.setInvoiceStatus("0");
                }
                this.workTaskDao.save(task);
                
                // 添加订单日志
                OrderLog orderlog = new OrderLog(ordeno, customerCode, "2", // 操作类型 （1.创建作业批次 2.创建作业任务 3.修正拣货信息 4.拣货完成 5.包装完成 6.发货完成 7.签收完成 8.异常登记）
                    user, now, null, user.getRealname() + "创建作业任务(" + task.getTaskCode() + ")");
                this.orderLogDao.save(orderlog);
                
                // 修改EdiOrder状态，添加 batch_task_code、backup_task_code信息
                EdiOrder ediOrder = this.ediOrderService.findByOrdeno(ordeno);
                ediOrder.setBatchTaskCode(task.getBatchCode());
                ediOrder.setBackupTaskCode(task.getTaskCode());
                this.ediOrderService.save(ediOrder);
            }
            
            // 创建作业任务项
            if (task.getPickType().equals("single")) {
                this.createWorkTaskItem_single(taskCode);
            } else {
                this.createWorkTaskItem_multi(taskCode);
            }
            
            // 添加工作日志
            WorkLog workLog1 = new WorkLog(batchCode, "2", user.getRealname() + "创建任务(" + task.getTaskCode() + ")", now, user);
            this.workLogDao.save(workLog1);
            
            // 查看同批次的订单是否都生成作业任务，如果是，修改批次状态为：2
            List<WorkOrder> untaskOrderList = this.workOrderDao.loadOrderByStatus(batchCode, "1");
            if (untaskOrderList.size() == 0) {
                workGuaranteeTaskService.saveWorkGuaranteeTask(batch.getBatchCode());
                batch.setStatus("2"); // 批次状态 (1.创建作业批次 2.创建作业任务 3.作业任务分配完 4.作业任务完成 5.包装任务完成 6.发货任务完成)
                this.workBatchDao.save(batch);
                
                // 添加工作日志
                WorkLog workLog = new WorkLog(batchCode, "2", "创建任务完成", now, null);
                this.workLogDao.save(workLog);
            }
            
            // 如果是限制订单流入的商家，消除订单预定数量 modify 20160920 放到最后
            Customers customer = this.customersDao.findByCustomerCode(customerCode);
            if ("1".equals(customer.getPlaceStatus())) { // 限制订单流入的商家
                
                List<WorkOrder> workOrderList = this.workOrderDao.loadOrderByTaskCode(taskCode);
                
                // 遍历订单，将订单的sku需求整理为：map<sku,num>格式
                Map<String, Integer> map = new HashMap<String, Integer>();
                for (WorkOrder workOrder : workOrderList) {
                    EdiOrder order = workOrder.getOrder();
                    List<EdiOrderItem> itemList = this.ediOrderItemDao.findByOrdeno(order.getOrdeno());
                    for (EdiOrderItem item : itemList) {
                        String sku = item.getSku();
                        int qty = item.getQty();
                        if (map.keySet().contains(sku)) {
                            map.put(sku, map.get(sku) + qty);
                        } else {
                            map.put(sku, qty);
                        }
                    }
                }
                
                // 订单预定数量回滚
                for (String sku : map.keySet()) {
                    int qty = map.get(sku);
                    /*CusStockMerge merge = this.cusStockMergeService.findCustomerWarSku(customerCode, warehouseCode, sku);
                    if (merge != null) {
                        int _orderNum = merge.getOrderNum();
                        int temp = _orderNum - qty;
                        if (temp < 0) {
                            log.error("预定库存异常，sku:" + sku + " ; 商家：" + customerCode + " ; 仓库：" + warehouseCode);
                        }
                        merge.setOrderNum(Math.max(temp, 0));
                        this.cusStockMergeService.save(merge);
                    }*/
                    /** modify 20160920 */
                    int cnt = this.cusStockMergeService.updateCusStockMerge(customerCode, warehouseCode, sku, qty);
                    if (cnt == 0) {
                        log.error("预定库存异常，sku:" + sku + " ; 商家：" + customerCode + " ; 仓库：" + warehouseCode);
                    }
                }
                
            }
            
            // add 20160920
            releaseCusStockTaskRollback(batchCode);
        } catch (Exception e) {
            throw e;
        }
        
        return true;
    }
    
    /**
     * 释放
     *
     * @param batchCode 批次号
     * @author <a href=mailto:yuanlianghe@nryuncang.com>yuanlianghe</a>
     * @version 1.0.0
     */
    public void releaseCusStockTaskRollback(String batchCode) {
        Query query = em.createNativeQuery("delete from cus_stock_task_rollback where batch_code=?");
        query.setParameter(1, batchCode);
        query.executeUpdate();
    }
    
    /**
     * 手工回滚库存数量
     * @author <a href=mailto:yuanlianghe@nryuncang.com>yuanlianghe</a>
     * @version 1.0.0
     */
    @Transactional(readOnly=false, rollbackFor=Exception.class, propagation=Propagation.REQUIRED)
    public void rollbackCusStockTask(String batchCode) {
        Query query = em.createNativeQuery("update cus_stock_task_rollback a, cus_stock b set b.sales_num=b.sales_num+a.num, b.order_num=b.order_num-a.num, b.version=b.version+?, a.status=? "
                           + "where b.customer_code=a.customer_code and b.warehouse_code=a.warehouse_code and b.stock_code=a.stock_code and b.box_code=a.box_code and b.sku=a.sku and a.batch_code=? and a.status=?");
        int i = 1;
        query.setParameter(i++, 1);
        query.setParameter(i++, 1);
        query.setParameter(i++, batchCode);
        query.setParameter(i++, 0);
        query.executeUpdate();
    }

    /**
     * 查询任务
     * @param batchCode 批次号
     * @return
     */
    public List<WorkTask> loadTaskByBatchCode(String batchCode) {
        List<WorkTask> workTaskList= this.workTaskDao.loadTaskByBatchCode(batchCode);
        this.setUser(workTaskList);
        return workTaskList;
    }
    
   /**
    * 加载任务者信息
    * @param workTaskList
    */
    public void setUser(List<WorkTask> workTaskList){
        for (WorkTask workTask : workTaskList) {
            if(workTask.getCreaterId()!=null){
                User creater=this.userDao.findOne(workTask.getCreaterId());
                workTask.setCreater(creater);
            }
            if(workTask.getPickerId()!=null){
                User picker=this.userDao.findOne(workTask.getPickerId());
                workTask.setPicker(picker);
            }
            if(workTask.getPkgerId()!=null){
                User pkger=this.userDao.findOne(workTask.getPkgerId());
                workTask.setPkger(pkger);
            }
            if(workTask.getSenderId()!=null){
                User sender=this.userDao.findOne(workTask.getSenderId());
                workTask.setSender(sender);
            }
            if(workTask.getAssignerId()!=null){
                User assigner=this.userDao.findOne(workTask.getAssignerId());
                workTask.setAssigner(assigner);
            }
        }
    }
    
    /**
    * 加载信息
    * @param workTaskList
    */
    public void setCustomerAndWarehouse(List<WorkTask> workTaskList){
        for (WorkTask workTask : workTaskList) {
            String customerCode=workTask.getCustomerCode();
            String warehouseCode=workTask.getWarehouseCode();
            String companyCode=workTask.getCompanyCode();
            if(StringUtils.isNotBlank(customerCode)){
                Customers customer=this.customersDao.findByCustomerCode(customerCode);
                workTask.setCustomer(customer);
            }
            if(StringUtils.isNotBlank(warehouseCode)){
                AreaGroup areagroup=this.areaGroupDao.findByGroupCode(warehouseCode);
                workTask.setWarehouse(areagroup);
            }
            if(StringUtils.isNotBlank(companyCode)){
                LogisticsCompany company=this.logisticsCompanyDao.findCompanyByCode(companyCode);
                workTask.setCompany(company);
            }
        }
    }

    /**
     * 指派拣货任务
     * @param taskId  任务ID
     * @param jobuuid 执行人JOBUUID
     * @return
     * @throws Exception
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public String commandPickTask(Long taskId, String jobuuid) throws Exception {
        try {
            String msg = null;
            User picker = this.userDao.findByJobuuid(jobuuid);

            WorkTask task = this.workTaskDao.findOne(taskId);
            if (!task.getStatus().equals("1")) {
                msg = "token"; // 任务已经被指派或者领取
            } else {
                task.setPickerId(picker.getId());
                task.setStatus("2");
                this.workTaskDao.save(task);
                msg = "success"; // 任务指派成功
            }
            return msg;

        } catch (Exception e) {
            
            throw new Exception(">>>指派作业任务异常");
        }

    }

    /**
     * 查找任务
     * @param param 查询参数
     * @return
     */
    public List<WorkTask> loadTaskByParam(Map<String, Object> param) {
        List<WorkTask> workTaskList = null;
        
        Specification<WorkTask> spec = getWhereClause(param);
        if (param.get("num") != null) {
            int pageNumber = 1;
            int pageSize = Integer.valueOf(param.get("num").toString()).intValue();
            PageRequest pageRequest = buildPageRequest(pageNumber, pageSize, "id_asc");
            workTaskList = this.workTaskDao.findAll(spec, pageRequest).getContent();
        } else {
            workTaskList = this.workTaskDao.findAll(spec);
        }

        this.setUser(workTaskList);
        this.setCustomerAndWarehouse(workTaskList);
        return workTaskList;
    }
    
    public Page<WorkTask> findByJson(QueryParamHolder paramHolder) {
        return findByJson(paramHolder, workTaskDao, WorkTask.class);
    }
    /**
     * 查询条件封装
     * @param param
     * @return
     */
    private Specification<WorkTask> getWhereClause(final Map<String, Object> param) {
        return new Specification<WorkTask>(){
            @Override
            public Predicate toPredicate(Root<WorkTask> r, CriteriaQuery<?> q, CriteriaBuilder cb) {
              Predicate pre = cb.conjunction();
              
              //customerCodes
              String customerCodes=(String) param.get("customerCodes");
              if(StringUtils.isNotBlank(customerCodes)) {
                  String[] customerCodeSplit = customerCodes.split(":");
                  ComparisonPredicate[] tempCustomerCode = new ComparisonPredicate[customerCodeSplit.length];
                  int i = 0;
                  for (String _customerCode : customerCodeSplit) {
                     tempCustomerCode[i] = (ComparisonPredicate) cb.equal(r.get("customerCode"), _customerCode);
                     i++;
                  }
                  pre.getExpressions().add(cb.or(tempCustomerCode));
              }
              
              
              //areagroups
              String areagroups=(String) param.get("areagroups");
              if(StringUtils.isNotBlank(areagroups)) {
                  String[] areagroupSplit = areagroups.split(":");
                  ComparisonPredicate[] areagroupArray = new ComparisonPredicate[areagroupSplit.length];
                  int j = 0;
                  for (String _areagroup : areagroupSplit) {
                        areagroupArray[j] = (ComparisonPredicate) cb.equal(r.get("warehouseCode"), _areagroup);
                        j++;
                  }
                  pre.getExpressions().add(cb.or(areagroupArray));
              }
              
                
              Date fromDate= (Date) param.get("fromDate");
              if (fromDate != null) {
                pre.getExpressions().add(cb.greaterThanOrEqualTo(r.<Date>get("createTime"), fromDate));
              }
              
              Date toDate= (Date) param.get("toDate");
              if (toDate != null) {
                pre.getExpressions().add(cb.lessThanOrEqualTo(r.<Date>get("createTime"), toDate));
              }
              
              String status=(String) param.get("status"); 
              if(StringUtils.isNotBlank(status)){
                  
                  if(status.equals("myLampPick")){ //我的灯光拣选任务
                      pre.getExpressions().add(cb.or(
                              cb.equal(r.get("status"),"4"),
                              cb.equal(r.get("status"),"10")
                              ));
                      
                  }else if(status.equals("2")){ //我拣选任务
                      pre.getExpressions().add(cb.or(
                              cb.equal(r.get("status"),"2"),
                              cb.equal(r.get("status"),"11"),
                              cb.equal(r.get("status"),"12")
                              ));
                      
                  }
                  else if(status.equals("pkg")){ //未分配的包装任务
                      pre.getExpressions().add(
                              cb.or(
                                     cb.and(cb.equal(r.get("status"),"5"),cb.equal(r.get("pickModel"),"lamp")),
                                     cb.and(cb.equal(r.get("status"),"4"),cb.notEqual(r.get("pickModel"),"car"))  
                              ));
                      
                  }
                  else{
                      pre.getExpressions().add(cb.equal(r.get("status"),status)); 
                  }
              }
              
            
              
              if(param.get("pickerId")!=null){
                  Long pickerId=(Long)(param.get("pickerId"));
                  pre.getExpressions().add(cb.or(cb.equal(r.get("pickerId"),pickerId),cb.equal(r.get("assignerId"), pickerId)));
              }    
              
              if(param.get("pkgerId")!=null){
                  Long pkgerId=(Long)(param.get("pkgerId"));
                  pre.getExpressions().add(cb.equal(r.get("pkgerId"),pkgerId));
              }    
              
              if(param.get("lamperId")!=null){
                  Long lamperId=(Long)(param.get("lamperId"));
                  pre.getExpressions().add(cb.equal(r.get("lamperId"),lamperId));
              }    
              
              String pickType=(String) param.get("pickType");
              if(StringUtils.isNotBlank(pickType)){
                    pre.getExpressions().add(cb.equal(r.get("pickType"),pickType));
              }    
              
              String pickModel=(String) param.get("pickModel");
              if(StringUtils.isNotBlank(pickModel)){
                    pre.getExpressions().add(cb.equal(r.get("pickModel"),pickModel));
              }    
              
              String batchType=(String) param.get("batchType");
              if(StringUtils.isNotBlank(batchType)){
                  pre.getExpressions().add(cb.equal(r.get("batchType"),batchType));
              }
              
              String printStatus=(String) param.get("printStatus");
              if(StringUtils.isNotBlank(printStatus)){
                  pre.getExpressions().add(cb.equal(r.get("printStatus"),printStatus));
              }
              
              String flowType=(String) param.get("flowType");
              if(StringUtils.isNotBlank(flowType)){
                  pre.getExpressions().add(cb.equal(r.get("flowType"),flowType));
              }
              
              String companyCode=(String) param.get("companyCode");
              if(StringUtils.isNotBlank(companyCode)){
                  pre.getExpressions().add(cb.equal(r.get("companyCode"),companyCode));
              }
              
              // begin 增加创建者查询条件 By rongfei.zhang
              String createrIds = (String) param.get("createrIds");
              if(StringUtils.isNotBlank(createrIds)){              
                  String[] createrIdSplit = createrIds.split(":");
                  ComparisonPredicate[] tempCreaterId = new ComparisonPredicate[createrIdSplit.length];
                  int i = 0;
                  for (String _createrId : createrIdSplit) {
                     tempCreaterId[i] = (ComparisonPredicate) cb.equal(r.get("createrId"), Long.parseLong(_createrId));
                     i++;
                  }
                  pre.getExpressions().add(cb.or(tempCreaterId));
              }
              // end 增加创建者查询条件 By rongfei.zhang
              
              // begin 增加任务编号查询条件 By rongfei.zhang
              String taskCode = (String) param.get("taskCode");
              if(StringUtils.isNotBlank(taskCode)){
                  pre.getExpressions().add(cb.equal(r.get("taskCode"),taskCode));
              }
              // end 增加任务编号查询条件 By rongfei.zhang
              
                // 优先派送标志
                String psFlag = (String) param.get("psFlag");
                if (StringUtils.isNotBlank(psFlag)) {
                    if ("-1".equals(psFlag)) {
                        ComparisonPredicate[] prioritySendFlagArray = new ComparisonPredicate[2];
                        prioritySendFlagArray[0] = (ComparisonPredicate) cb.equal(r.get("prioritySendFlag"), "0");
                        prioritySendFlagArray[1] = (ComparisonPredicate) cb.equal(r.get("prioritySendFlag"), "1");
                        pre.getExpressions().add(cb.or(prioritySendFlagArray));
                    } else {
                        pre.getExpressions().add(cb.equal(r.get("prioritySendFlag"), psFlag));
                    }
                }
              
              return pre;
            }
          };
      }

    /**
     * 查询作业任务
     * @param taskId 任务Id
     * @return
     */
    public WorkTask loadTaskById(Long taskId) {
        WorkTask task=this.workTaskDao.findOne(taskId);
        if(task!=null){
            Customers customer=this.customersDao.findByCustomerCode(task.getCustomerCode());
            task.setCustomer(customer);
            AreaGroup warehouse=this.areaGroupDao.findByGroupCode(task.getWarehouseCode());
            task.setWarehouse(warehouse);
        }
        return task;
    }

    /**
     * 根据任务号与任务状态查找对应任务
     * 
     * @param taskCode 任务编号
     * @param status 任务状态
     * @return
     */
    public List<WorkTask> loadTaskByTaskCodeAndStatus(String taskCode, String status) {
        WorkTask task=this.workTaskDao.loadTaskByTaskCodeAndStatus(taskCode, status);
        List<WorkTask> workTaskList=new ArrayList<WorkTask>();
        if(task!=null){
            workTaskList.add(task);
            this.setUser(workTaskList);
            this.setCustomerAndWarehouse(workTaskList);
        }
        return workTaskList;
    }
    
    /**
     * 查找未完成的任务
     * @param batchCode 批次号
     * @return
     */
    private List<WorkTask> loadTask(String batchCode,String status) {
        return this.workTaskDao.loadTask(batchCode,status);
    }
    
    /**
     * 根据任务号查找对应任务
     * @param taskCode 任务号
     * @return
     */
    public List<WorkTask> loadTaskByTaskCode(String taskCode) {
        WorkTask task=this.workTaskDao.loadTaskByTaskCode(taskCode);
        List<WorkTask> workTaskList=new ArrayList<WorkTask>();
        if(task!=null){
            workTaskList.add(task);
            this.setUser(workTaskList);
            this.setCustomerAndWarehouse(workTaskList);
        }
        return workTaskList;
    }

    /**
     * 查询包装任务
     * @param param
     * @return
     */
    public List<WorkTask> loadPkgTask(Map<String, Object> param) {
        Specification<WorkTask> spec = getWhereClause_pkg(param);
        List<WorkTask> workTaskList = this.workTaskDao.findAll(spec);
        return workTaskList;
    }
    
    /**
     * 查询条件封装
     * @param param
     * @return
     */
    private Specification<WorkTask> getWhereClause_pkg(final Map<String, Object> param) {
        return new Specification<WorkTask>(){
            @Override
            public Predicate toPredicate(Root<WorkTask> r, CriteriaQuery<?> q, CriteriaBuilder cb) {
              Predicate pre = cb.conjunction();
              
              String customerCode=(String) param.get("customerCode");
              if(StringUtils.isNotEmpty(customerCode)){
                    pre.getExpressions().add(cb.equal(r.get("customerCode"),customerCode));
              }

              Date fromDate= (Date) param.get("fromDate");
              if (fromDate != null) {
                pre.getExpressions().add(cb.greaterThanOrEqualTo(r.<Date>get("createTime"), fromDate));
              }
              
              Date toDate= (Date) param.get("toDate");
              if (toDate != null) {
                pre.getExpressions().add(cb.lessThanOrEqualTo(r.<Date>get("createTime"), toDate));
              }
              
              String status=(String) param.get("status"); //任务状态( 1.创建作业任务 2.已指派作业任务 3.单据上架（灯光架、作业车） 4.完成作业任务 5.完成包装作业 6.完成发货作业)
              if(StringUtils.isEmpty(status)){
                  pre.getExpressions().add(
                          cb.or(
                                  cb.equal(r.get("status"),"4"),
                                  cb.equal(r.get("status"),"5"),
                                  cb.equal(r.get("status"),"6")
                         )
                 );
              }else if("5,6".equals(status)){
                  pre.getExpressions().add(
                          cb.or(
                                  cb.equal(r.get("status"),"5"),
                                  cb.equal(r.get("status"),"6")
                         )
                 );
              }else{
                  pre.getExpressions().add( cb.equal(r.get("status"),"4"));
              } 
              
              String workType=(String) param.get("workType");
              if(StringUtils.isNotEmpty(workType)){
                    pre.getExpressions().add(cb.equal(r.get("workType"),workType));
              } 
              
              String batchType=(String) param.get("batchType");
              if(StringUtils.isNotEmpty(batchType)){
                  pre.getExpressions().add(cb.equal(r.get("batchType"),batchType));
              }
              
              String warehouseCode=(String) param.get("warehouseCode");
              if(StringUtils.isNotEmpty(warehouseCode)){
                  pre.getExpressions().add(cb.equal(r.get("warehouseCode"),warehouseCode));
              }
              return pre;
            }
          };
      }

    /**
     * 完成包装任务
     * @param taskId
     * @throws Exception
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public void completePkgTask(Long taskId) throws Exception {
        try {
            Date now=new Date();
            ShiroUser curUser = (ShiroUser) SecurityUtils.getSubject().getPrincipal();
            User user=this.userDao.findByJobuuid(curUser.jobuuid);
            
            //修改任务状态
            WorkTask task=this.loadTaskById(taskId);
            task.setStatus("6"); //任务状态( 1.创建任务 2.已分配拣货任务 3.单据上架（灯光架、拣货车） 4.已拣货 5.已分配包装任务 6.已包装 7.已分配发货任务 8.已发货)
            this.workTaskDao.save(task);
            
            //添加工作日志
            WorkLog workLog1=new WorkLog(
                    task.getBatchCode(),
                    "4", //操作类型 (1.创建批次 2.创建任务 3.完成拣货 4.完成包装 5.完成发货   )
                    "完成包装任务（"+task.getTaskCode()+"）", 
                    now, 
                    user);
            this.workLogDao.save(workLog1);
            
            //修改订单状态，添加日志
            List<WorkOrder> orderList=this.workOrderDao.loadOrderByTaskCode(task.getTaskCode());
            List<OrderLog> logList=new ArrayList<OrderLog>();
            for (WorkOrder order : orderList) {
                order.setStatus("4"); //订单状态 (1.创建拣货批次 2.创建拣货任务 3.已拣货 4.已包装 5.已发货 6.已签收 7.异常登记)
                OrderLog log=new OrderLog(
                        order.getOrder().getOrdeno(),
                        task.getCustomerCode(),
                        "5", //操作类型 （1.创建作业批次 2.创建作业任务 3.修正作业信息 4.作业完成 5.包装完成 6.发货完成 7.签收完成）
                        user,
                        now,
                        null,
                        user.getRealname()+"完成包装");
                logList.add(log);
            }
            
            this.workOrderDao.save(orderList);
            this.orderLogDao.save(logList);
            
            //查看同一批次的其他任务是否完成，如果都完成，修改入库批次状态为：5
            List<WorkTask> uncompletedTaskList=this.loadTask(task.getBatchCode(),"5");
            if(uncompletedTaskList==null || uncompletedTaskList.size()==0){
                WorkBatch batch=this.workBatchDao.loadbatchByBatchCode(task.getBatchCode());
                batch.setStatus("4"); //批次状态 (1.已创建批次 2.已创建任务 3.已拣货 4.已包装 5.已发货)
                this.workBatchDao.save(batch);
                
                //添加工作日志
                WorkLog workLog=new WorkLog(
                        task.getBatchCode(),
                        "2",
                        "包装任务全部完成", 
                        now, 
                        null);
                this.workLogDao.save(workLog);
            }
            
        } catch (Exception e) {
            throw new Exception(e);
        }
    }


    
    @Transactional(readOnly = true)
    public WorkTask findByTaskId(Long id){
        return workTaskDao.findOne(id);
    }

    /**
     * 领取任务
     * @param taskId 任务ID
     * @param userId 任务执行人
     * @param taskType 任务类型 （ pick:拣货  lampPick:灯光拣选   pkg:包装    send:发货 ）
     * @throws Exception 
     */
    @Transactional(readOnly = false, rollbackFor=Exception.class)
    public void takeTask(Long taskId, Long userId, String taskType) throws Exception {
        
        try {
            WorkTask task=this.workTaskDao.findOne(taskId);
            User curUser=this.userDao.findOne(userId);
            Date now=new Date();
            WorkLog workLog=null;
            
            //任务状态( 1.创建任务 2.已分配拣货任务 3.已拣货 4. 已分配灯光拣选任务 5.已经灯光拣选 6.已分配包装任务 7.已包装 8.已分配发货任务 9.已发货 10.灯光拣选进行中.. 11.推车拣选进行中.. 12.拣货中...)
            //操作类型 (1.创建批次 2.创建任务 3.领取拣货任务  4.完成拣货任务 5.领取灯光拣选任务 6.完成灯光拣选任务  7.领取包装任务 8完成包装任务  9.领取发货任务  10.完成发货任务   )
            if(taskType.equals("pick")){
                if (task.getPickerId() != null) {
                    return;
                }
                task.setPickerId(userId);
                task.setStatus("2"); 
                workLog=new WorkLog(task.getBatchCode(),"3", curUser.getRealname()+"领取拣货任务("+task.getTaskCode()+")", now, curUser);
            }
            else if(taskType.equals("lampPick")){
                if (task.getLamperId() != null) {
                    return;
                }
                task.setLamperId(userId);
                task.setStatus("4");
                workLog=new WorkLog(task.getBatchCode(),"5", curUser.getRealname()+"领取灯光拣选任务("+task.getTaskCode()+")", now, curUser);
            }
            else if(taskType.equals("pkg")){
                if (task.getPkgerId() != null) {
                    return;
                }
                task.setPkgerId(userId);
                task.setStatus("6"); 
                workLog=new WorkLog(task.getBatchCode(),"7", curUser.getRealname()+"领取包装任务("+task.getTaskCode()+")", now, curUser);
            }
            else if(taskType.equals("send")){
                if (task.getSenderId() != null) {
                    return;
                }
                task.setSenderId(userId);
                task.setStatus("8"); 
                workLog=new WorkLog(task.getBatchCode(),"9", curUser.getRealname()+"领取发货任务("+task.getTaskCode()+")", now, curUser);
            }
            
            this.workTaskDao.save(task);
            
            //工作日志
            this.workLogDao.save(workLog);
        
        } catch (Exception e) {
            throw new Exception(e);
        }
    }
    
    

    /**
     * 查询拣货信息，并按库位排序—多件
     * @param taskId
     * @return
     */
    public List<Map.Entry<String,Integer>> loadPrintInfo_multi(String taskCode) {
        
        List<WorkOrder> orderList=this.workOrderDao.loadOrderByTaskCode(taskCode);
        
        Map<String, Integer> map=new HashMap<String, Integer>();
        
        //组合订单的取货信息
        for (WorkOrder order : orderList) {
            
            String stockInfo=order.getStockInfo();
            String[] stockInfoSplit=stockInfo.split(";");
            
            for (String info : stockInfoSplit) {
                
                try {
                    
                    String[] infoSplit=info.split("_");
                    String stockCode=infoSplit[0];
                    String boxCode=infoSplit[1];
                    String sku=infoSplit[2];
                    String num=infoSplit[3];
                    
                    String key=stockCode+"_"+boxCode+"_"+sku;
                    Integer value=Integer.valueOf(num);
                    
                    if(map.containsKey(key)){
                        map.put(key, map.get(key)+value);
                    }else{
                        map.put(key, value);
                    }
                
                } catch (Exception e) {
                    
                }
            }
            
        }
        
        //按库位排序
        List<Map.Entry<String,Integer>> mapList=new ArrayList<Map.Entry<String,Integer>>(map.entrySet());
        Collections.sort(mapList, new Comparator<Map.Entry<String,Integer>>() {
            @Override
            public int compare(Entry<String, Integer> o1,Entry<String, Integer> o2) {
                return o1.getKey().compareTo(o2.getKey());
            }
        });
        
        return mapList;
    }
    
    /**
     * 多件
     * @param taskId
     * @return
     * @throws Exception 
     */
    @Transactional(readOnly = false,rollbackFor=Exception.class)
    public void createWorkTaskItem_multi(String taskCode) throws Exception {
        
        try {
        
        WorkTask task=this.workTaskDao.loadTaskByTaskCode(taskCode);
        List<WorkOrder> orderList=this.workOrderDao.loadOrderByTaskCode(taskCode);
        List<WorkTaskItem> itemList=new ArrayList<WorkTaskItem>();
        Map<String, Integer> map=new HashMap<String, Integer>();
        
        //组合订单的取货信息
        for (WorkOrder order : orderList) {
            
            String stockInfo=order.getStockInfo();
            String[] stockInfoSplit=stockInfo.split(";");
            for (String info : stockInfoSplit) {
                try {
                    String[] infoSplit=info.split("_");
                    String stockCode=infoSplit[0];
                    String boxCode=infoSplit[1];
                    String sku=infoSplit[2];
                    String num=infoSplit[3];
                    
                    String key=stockCode+"_"+boxCode+"_"+sku;
                    Integer value=Integer.valueOf(num);
                    
                    if(map.containsKey(key)){
                        map.put(key, map.get(key)+value);
                    }else{
                        map.put(key, value);
                    }
                    
                } catch (Exception e) {
                    
                }
            }
            
        }
        
        //按库位排序
        List<Map.Entry<String,Integer>> mapList=new ArrayList<Map.Entry<String,Integer>>(map.entrySet());
        Collections.sort(mapList, new Comparator<Map.Entry<String,Integer>>() {
            @Override
            public int compare(Entry<String, Integer> o1,Entry<String, Integer> o2) {
                return o1.getKey().compareTo(o2.getKey());
            }
        });
        
        
        //create workTaskItem
        int i=0;
        for (Entry<String, Integer> entry : mapList) {
            String stockInfo=entry.getKey();
            Integer num=entry.getValue();
            String[] stockInfoSplit=stockInfo.split("_");
            String stockCode=stockInfoSplit[0];
            String boxCode=stockInfoSplit[1];
            String sku=stockInfoSplit[2];
            
            WorkTaskItem item=new WorkTaskItem();
            item.setBatchCode(task.getBatchCode());
            item.setTaskCode(task.getTaskCode());
            item.setRankno(++i);
            item.setCustomerCode(task.getCustomerCode());
            item.setWarehouseCode(task.getWarehouseCode());
            item.setPickedNum(0);
            item.setPickStatus("unpicked"); //拣货状态（picked:已拣 unpicked:未拣）
            
            item.setOrderno("");
            item.setStockCode(stockCode);
            item.setBoxCode(boxCode);
            item.setSku(sku);
            item.setNum(num);
            item.setPickedNum(0);
            
            itemList.add(item);
        }
        this.workTaskItemDao.save(itemList);
        
        } catch (Exception e) {
            throw new Exception(e);
        }
        
    }
    
    /**
     * 单件
     * @param taskId
     * @return
     */
    @Transactional(readOnly = false,rollbackFor=Exception.class)
    public void createWorkTaskItem_single(String taskCode) throws Exception {
        
            WorkTask task=this.workTaskDao.loadTaskByTaskCode(taskCode);
            String flowType=task.getFlowType();
            
            List<WorkOrder> orderList=this.workOrderDao.loadOrderByTaskCode(taskCode);
            List<WorkTaskItem> itemList=new ArrayList<WorkTaskItem>();
            Map<String, Object> map=new LinkedHashMap<String, Object>();
            List<Map.Entry<String,Object>> mapList=null;
            
            if(flowType.equals("intimePrint")){ //及时打单
                //组合订单的取货信息
                for (WorkOrder order : orderList) {
                    String stockInfo=order.getStockInfo();
                    String[] stockInfoSplit=stockInfo.split(";");
                    
                    for (String info : stockInfoSplit) {
                        try {
                            String[] infoSplit=info.split("_");
                            String stockCode=infoSplit[0];
                            String boxCode=infoSplit[1];
                            String sku=infoSplit[2];
                            String num=infoSplit[3];
                            
                            String key=stockCode+"_"+boxCode+"_"+sku;
                            Integer value=Integer.valueOf(num);
                            
                            if(map.containsKey(key)){
                                Integer temp=(Integer)map.get(key);
                                map.put(key, temp+value);
                            }else{
                                map.put(key, value);
                            }
                        } catch (Exception e) {
                            
                        }
                    }
                }
                
                //按库位排序
                mapList=new ArrayList<Map.Entry<String,Object>>(map.entrySet());
                Collections.sort(mapList, new Comparator<Map.Entry<String,Object>>() {
                    @Override
                    public int compare(Entry<String, Object> o1,Entry<String, Object> o2) {
                        return o1.getKey().compareTo(o2.getKey());
                    }
                });
            }
            else if(flowType.equals("prePrint")){ //预先打单
                
                /**
                 * 修改拣货模式，注释较早的代码 by ch 20140402
                mapList=new ArrayList<Map.Entry<String,Object>>(map.entrySet());
                for (WorkOrder order : orderList) {
                    String orderno=order.getOrder().getOrdeno();
                    String info=order.getStockInfo();
                    map.put(orderno, info);
                }
               **/
                
                /**
                 * 修改拣货模式，添加的代码 by ch 20140402
                 */
                for (WorkOrder order : orderList) { //组合订单的取货信息
                    String stockInfo=order.getStockInfo();
                    String[] stockInfoSplit=stockInfo.split(";");
                    
                    for (String info : stockInfoSplit) {
                            String[] infoSplit=info.split("_");
                            String stockCode=infoSplit[0];
                            String boxCode=infoSplit[1];
                            String sku=infoSplit[2];
                            String num=infoSplit[3];
                            
                            String key=stockCode+"_"+boxCode+"_"+sku;
                            Integer value=Integer.valueOf(num);
                            
                            if(map.containsKey(key)){
                                Integer temp=(Integer)map.get(key);
                                map.put(key, temp+value);
                            }else{
                                map.put(key, value);
                            }
                    }
                }
                
                mapList=new ArrayList<Map.Entry<String,Object>>(map.entrySet());
            }
            
            int i=0;
            //create workTaskItem
            for (Entry<String, Object> entry : mapList) {
                
                String key=entry.getKey();
                Object value=entry.getValue();
                
                WorkTaskItem item=new WorkTaskItem();
                item.setBatchCode(task.getBatchCode());
                item.setTaskCode(task.getTaskCode());
                item.setRankno(++i);
                item.setCustomerCode(task.getCustomerCode());
                item.setWarehouseCode(task.getWarehouseCode());
                item.setPickStatus("unpicked"); //拣货状态（picked:已拣 unpicked:未拣）
                
                
                /**
                 * 修改拣货模式，添加的代码 by ch 20140402
                 */
                String[] stockInfoSplit=key.split("_");
                String stockCode=stockInfoSplit[0];
                String boxCode=stockInfoSplit[1];
                String sku=stockInfoSplit[2];
                Integer num=(Integer)value;
                
                item.setOrderno("");
                item.setStockCode(stockCode);
                item.setBoxCode(boxCode);
                item.setSku(sku);
                item.setNum(num);
                item.setPickedNum(0);
                
                
                /**
                 * 修改拣货模式，注释较早的代码 by ch 20140402
                 * 
                if(flowType.equals("intimePrint")){ //及时打单
                    String[] stockInfoSplit=key.split("_");
                    String stockCode=stockInfoSplit[0];
                    String boxCode=stockInfoSplit[1];
                    String sku=stockInfoSplit[2];
                    Integer num=(Integer)value;
                    
                    item.setOrderno("");
                    item.setStockCode(stockCode);
                    item.setBoxCode(boxCode);
                    item.setSku(sku);
                    item.setNum(num);
                    item.setPickedNum(0);
                }
                else if(flowType.equals("prePrint")){ //预先打单
                    String[] stockInfoSplit=value.toString().split("_");
                    String stockCode=stockInfoSplit[0];
                    String boxCode=stockInfoSplit[1];
                    String sku=stockInfoSplit[2];
                    
                    item.setOrderno(key);
                    item.setStockCode(stockCode);
                    item.setBoxCode(boxCode);
                    item.setSku(sku);
                    item.setNum(1);
                    item.setPickedNum(0);
                }
                **/
                
                itemList.add(item);
            }
            
            this.workTaskItemDao.save(itemList);

    }
    
    
    /**
     * 查询拣货信息，并按库位排序-单件
     * @param taskId
     * @return
     */
    public List<Map.Entry<String,Object>> loadPrintInfo_single(String taskCode) {
        
        WorkTask task=this.workTaskDao.loadTaskByTaskCode(taskCode);
        String flowType=task.getFlowType();
        
        List<WorkOrder> orderList=this.workOrderDao.loadOrderByTaskCode(taskCode);
        
        Map<String, Object> map=new LinkedHashMap<String, Object>();
        List<Map.Entry<String,Object>> mapList=null;
        
        if(flowType.equals("intimePrint")){ //及时打单
            //组合订单的取货信息
            for (WorkOrder order : orderList) {
                String stockInfo=order.getStockInfo();
                String[] stockInfoSplit=stockInfo.split(";");
                
                for (String info : stockInfoSplit) {
                    try {
                        String[] infoSplit=info.split("_");
                        String stockCode=infoSplit[0];
                        String boxCode=infoSplit[1];
                        String sku=infoSplit[2];
                        String num=infoSplit[3];
                        
                        String key=stockCode+"_"+boxCode+"_"+sku;
                        Integer value=Integer.valueOf(num);
                        
                        if(map.containsKey(key)){
                            Integer temp=(Integer)map.get(key);
                            map.put(key, temp+value);
                        }else{
                            map.put(key, value);
                        }
                    } catch (Exception e) {
                        log.error("查询拣货信息异常,taskCode="+taskCode, e);
                    }
                }
            }
            
            //按库位排序
            mapList=new ArrayList<Map.Entry<String,Object>>(map.entrySet());
            Collections.sort(mapList, new Comparator<Map.Entry<String,Object>>() {
                @Override
                public int compare(Entry<String, Object> o1,Entry<String, Object> o2) {
                    return o1.getKey().compareTo(o2.getKey());
                }
            });
        }
        else if(flowType.equals("prePrint")){ //预先打单
            
            mapList=new ArrayList<Map.Entry<String,Object>>(map.entrySet());
            for (WorkOrder order : orderList) {
                String orderno=order.getOrder().getOrdeno();
                String info=order.getStockInfo();
                map.put(orderno, info);
            }
            
            mapList=new ArrayList<Map.Entry<String,Object>>(map.entrySet());
            
        }
        
        return mapList;
    }

    /**
     * 查询任务
     * @param taskCode 任务编号
     * @return
     */
    public WorkTask loadTaskByCode(String taskCode) {
        return this.workTaskDao.loadTaskByTaskCode(taskCode);
    }



    /**
     * 包装
     * @param orderno 订单号
     * @return
     * @throws Exception 
     */
    @Transactional(readOnly = false,rollbackFor=Exception.class)
    public String pkg(String orderno,String jobuuid) throws Exception {
                
                User user=this.userDao.findByJobuuid(jobuuid);
                WorkOrder workOrder=this.workOrderDao.loadOrderByOrderno(orderno);
                Date now=new Date();
                if(null == workOrder){
                    return "unfound";
                }
                //状态不在包装
                String status=workOrder.getStatus();
                if(!"9".equals(status)){
                    if("5".equals(status) || "6".equals(status) || "7".equals(status) ){
                        return "pkged"; //已包装
                    }else{
                        return "error"; //不在包装状态
                    }
                }
                
                //取消单
                if("cancel".equals( workOrder.getCancelStatus() )){
                    return "cancel";
                }else{
                    ExceptionOrder exceptionOrder = exceptionOrderDao.loadByOrderno(workOrder.getOrder().getOrdeno());
                    if(exceptionOrder != null){
                        //设置订单状态:取消
                        workOrder.getOrder().setOrderStatus("cancel");
                        ediOrderService.save(workOrder.getOrder());
                        //设置作业单状态:取消
                        workOrder.setCancelStatus("cancel");
                        workOrderDao.save(workOrder);
                        return "cancel";
                    }
                }
                
                //如果是运单未打印，不能包装
                if(!"printed".equals( workOrder.getPrintStatus() )){
                    return "unprinted";//未打印
                }
                
                //修改订单状态
                workOrder.setStatus("5");//订单状态 (1.创建批次 2.创建任务 3.已拣货  4.已灯光拣选  9.待包装   5.已包装  6.已发货  7.已签收  8.异常 )
                workOrder.setPkgLock("pkged");//包装锁（pkging:包装中  unpkg:未包装   pkged: 已包装）
                this.workOrderDao.save(workOrder);
                log.info("订单号:"+orderno+"修改后的状态:"+workOrder.getStatus());
                
//              //淘宝订单全链路信息回传:已包装
//              try {
//                  new TaoBaoAPITool().resendOrderStatus(orderno, "X_PACKAGED");
//              } catch (Exception e) {
//                  
//              }
                
                //订单日志
                OrderLog orderLog=new OrderLog(
                        workOrder.getOrder().getOrdeno(),
                        workOrder.getCustomerCode(),
                        "4", //操作类型 （1.创建批次 2.创建任务  3.拣货完成 4.包装完成 5.发货完成 6.签收完成 7.异常登记 8.完成灯光拣选任务 9.打印单据）
                        user,
                        now,
                        null,
                        user.getRealname()+"完成包装");
                this.orderLogDao.save(orderLog);
                
                
                //查看同一任务其他订单是否完成包装
                List<WorkOrder> unPkgOrderList=this.workOrderDao.loadUnPkgOrderForTask(workOrder.getTaskCode());
                if(unPkgOrderList.size()==0){
                    
                    //任务状态
                    WorkTask task=this.workTaskDao.loadTaskByTaskCode(workOrder.getTaskCode());
                    task.setStatus("7");//任务状态( 1.创建任务 2.已分配拣货任务  3.已拣货  4. 已分配灯光拣选任务  5.已经灯光拣选  6.已分配包装任务  7.已包装  8.已分配发货任务  9.已发货  10.灯光拣选进行中.. 11.推车拣选进行中..)
                    this.workTaskDao.save(task);
                    
                    //作业日志
                    WorkLog workLog=new WorkLog(
                            task.getBatchCode(),
                            "8", //操作类型 (1.创建批次 2.创建任务 3.领取拣货任务  4.完成拣货任务 5.领取灯光拣选任务 6.完成灯光拣选任务  7.领取包装任务 8完成包装任务  9.领取发货任务  10.完成发货任务   )
                            "完成包装任务("+task.getTaskCode()+")",
                            now,
                            null);
                    this.workLogDao.save(workLog);
                    
                    //释放流转箱
                    String boxCode=task.getBoxCode();
                    if(StringUtils.isNotBlank(boxCode)){
                        WorkBox box=this.workBoxDao.loadByBoxCode(boxCode, task.getWarehouseCode());
                        box.setStatus("free");
                        box.setTaskCode(null);
                        this.workBoxDao.save(box);
                    }
                    
                }
                
                //查看同一批次其他订单是否完成包装
                List<WorkOrder> _unPkgOrderList=this.workOrderDao.loadUnPkgOrderForBatch(workOrder.getBatchCode());
                if(_unPkgOrderList!=null && _unPkgOrderList.size()==0){
                    
                    //任务状态
                    WorkBatch batch=this.workBatchDao.loadbatchByBatchCode(workOrder.getBatchCode());
                    batch.setStatus("4");//批次状态 (1.已创建批次 2.已创建任务 3.已拣货  4.已包装  5.已发货)
                    this.workBatchDao.save(batch);
                    
                    //作业日志
                    WorkLog workLog=new WorkLog(
                            batch.getBatchCode(),
                            "8", //操作类型 (1.创建批次 2.创建任务 3.领取拣货任务  4.完成拣货任务 5.领取灯光拣选任务 6.完成灯光拣选任务  7.领取包装任务 8完成包装任务  9.领取发货任务  10.完成发货任务   )
                            "完成全部包装",
                            now,
                            null);
                    this.workLogDao.save(workLog);
                    
                }
                //分配运单号caomingwu
                /*String ordenos ="";
                List<WorkOrder> workOrders = workOrderService.findByTaskCode(workOrder.getTaskCode()) ;
                for(WorkOrder order:workOrders){
                    ordenos += order.getOrder().getOrdeno()+":" ;
                }
                //LogisticsCompany company=this.logisticsCompanyDao.findCompanyByCode(workOrder.getExpressCompany());
                Long expressId = expressStyleService.findStyle(workOrder.getExpressCompany(), workOrder.getCustomerCode(), workOrder.getWarehouseCode()).get(0).getId() ;
                log.info(ordenos+"=============="+expressId+"================"+workOrder.getTaskCode());
                pickPrintUtil.printExpress(ordenos ,expressId,workOrder.getTaskCode()) ;*/

                /* begin remove 20160607 采用异步job的方式 by lianghe.yuan */
               /**
                try{
                    log.info("-----发送奇门出库单流水信息 已包装 orderno"+orderno);
                    Map<String,Object> params = new HashMap<String,Object>();
                    EdiOrder ediOrder = ediOrderDao.findByOrdeno(orderno);
                    params.put("ediOrder", ediOrder);
                    params.put("status", "package");
                    deliveryProcessService.send(params,ediOrder.getCustomerCode());
                    log.info("-----发送奇门出库单流水信息发送完毕  已包装 end");
                }catch(Exception e){
                    log.info("-----发送奇门出库单流水信息发送异常  已包装  error");
                }*/
               /* end remove 20160607 采用异步job的方式 by lianghe.yuan */
               
               /* begin add 20160607 先保存到任务表 by lianghe.yuan */
               InterfaceTask task = new InterfaceTask();
               task.setType(InterfaceTaskEnum.TYPE_QM_DELIVERY_PACKAGE);
               task.setRelatedNo(orderno);
               task.setCreatedTime(new Date());
               interfaceTaskService.saveTask(task);
               /* end add 20160607 先保存到任务表 by lianghe.yuan */

               return "success";
    }
    
    /**
     * 批量复核
     * @param orderno 订单号
     * @return
     * @throws Exception 
     */
    @Transactional(readOnly = false,rollbackFor=Exception.class)
    public String pkgBatch(String taskCode,String jobuuid) throws Exception {
            log.info("-----开始批量复核 taskCode="+taskCode);
            User user=this.userDao.findByJobuuid(jobuuid);
            this.workOrderDao.updateStatusByTaskCode("5", taskCode);
            //任务状态
            WorkTask task=this.workTaskDao.loadTaskByTaskCode(taskCode);
            if("7".equals(task.getStatus()) || "8".equals(task.getStatus()) || "9".equals(task.getStatus()))
            {
                return "status_error";
            }
            task.setStatus("7");//任务状态( 1.创建任务 2.已分配拣货任务  3.已拣货  4. 已分配灯光拣选任务  5.已经灯光拣选  6.已分配包装任务  7.已包装  8.已分配发货任务  9.已发货  10.灯光拣选进行中.. 11.推车拣选进行中..)
            this.workTaskDao.save(task);
            
            //作业日志
            WorkLog workLog=new WorkLog(
                    task.getBatchCode(),
                    "8", //操作类型 (1.创建批次 2.创建任务 3.领取拣货任务  4.完成拣货任务 5.领取灯光拣选任务 6.完成灯光拣选任务  7.领取包装任务 8完成包装任务  9.领取发货任务  10.完成发货任务   )
                    "完成批量复核("+task.getTaskCode()+")",
                    new Date(),
                    user);
            this.workLogDao.save(workLog);
            
            //释放流转箱
            String boxCode=task.getBoxCode();
            if(StringUtils.isNotBlank(boxCode)){
                WorkBox box=this.workBoxDao.loadByBoxCode(boxCode, task.getWarehouseCode());
                box.setStatus("free");
                box.setTaskCode(null);
                this.workBoxDao.save(box);
            }
                
            
            //查看同一批次其他订单是否完成包装
            List<WorkOrder> _unPkgOrderList=this.workOrderDao.loadUnPkgOrderForBatch(task.getBatchCode());
            if(_unPkgOrderList!=null && _unPkgOrderList.size()==0){
                
                //任务状态
                WorkBatch batch=this.workBatchDao.loadbatchByBatchCode(task.getBatchCode());
                batch.setStatus("4");//批次状态 (1.已创建批次 2.已创建任务 3.已拣货  4.已包装  5.已发货)
                this.workBatchDao.save(batch);
                
                //作业日志
                WorkLog workLog2=new WorkLog(
                        batch.getBatchCode(),
                        "8", //操作类型 (1.创建批次 2.创建任务 3.领取拣货任务  4.完成拣货任务 5.领取灯光拣选任务 6.完成灯光拣选任务  7.领取包装任务 8完成包装任务  9.领取发货任务  10.完成发货任务   )
                        "完成批量复核",
                        new Date(),
                        user);
                this.workLogDao.save(workLog2);
                
            }
            
            return "success";
        

    }


    /**
     * 
     * @param taskItemId 拣货任务项ID
     * @param sku  sku编码
     * @param pickNum 拣货的数量
     * @return 'coutinue'       : 拣货成功,继续此任务项拣货
     *         'finished'       : 此任务项已完成
     *         'finishing'      : 拣货成功,此任务项完成
     *         'task_finishing' : 拣货成功,此任务已经完成
     *         'error'          : 验证不通过
     * @throws Exception 
     */
    @Transactional(readOnly = false,rollbackFor=Exception.class)
    public String  pickAll(String taskCode) throws Exception {
        String msg="error";
    
        try {
            WorkTask task=this.workTaskDao.loadTaskByTaskCode(taskCode);
            List<WorkTaskItem> items = workTaskItemDao.loadUnPickItemByTaskCode((taskCode));
            Long totelPickNum = task.getPickedNum();
            for(WorkTaskItem item:items){
                
                //add 20160621 此为一键拣货逻辑，防止意外，加个校验
                if (item.getPickedNum() > 0) {
                    throw new RuntimeException("一键拣货，但是已拣货数量大于0，订单号：" + item.getOrderno());
                }
        
                int num=item.getNum();
                int _pickedNum=item.getPickedNum();
                int pickNum = num-_pickedNum;
                int pickedNum=_pickedNum+pickNum;
                item.setPickedNum(pickedNum);
                
    
                totelPickNum += pickNum;
                item.setPickStatus("picked");
    
                //this.workTaskDao.save(task);
                
                this.workTaskItemDao.save(item);
                
                //修改库存状态：从订单占用状态减去
                //modify 20160921 放到最后 bug:525
//                String _customerCode=item.getCustomerCode();
//                String _warehouseCode=item.getWarehouseCode();
//                String _stockCode=item.getStockCode();
//                String _boxCode=item.getBoxCode();
//                String _sku=item.getSku();
//                CusStock _stock=this.cusStockDao.loadStock(_customerCode, _warehouseCode, _stockCode, _boxCode, _sku);
//                if(_stock.getOrderNum() - pickNum < 0){//update by LiBin 20160808 原来是_stock.getOrderNum()<=0
//                    throw new Exception("订单占用库存异常：订单号："+item.getOrderno()+" sku:"+_sku);
//                }
//                _stock.setOrderNum(_stock.getOrderNum()-pickNum);
//                this.cusStockDao.save(_stock);
                
                //拣货成功，写入出库信息
                OutstorageInfo info=this.outstorageInfoService.loadByTaskCode(item.getTaskCode(),item.getSku());
                if(info==null){
                    info=new OutstorageInfo();
                    info.setCustomerCode(item.getCustomerCode());
                    info.setWarehouseCode(item.getWarehouseCode());
                    info.setBatchCode(item.getBatchCode());
                    info.setTaskCode(item.getTaskCode());
                    info.setSku(item.getSku());
                    info.setOpeTime(task.getCreateTime());
                    info.setAboutCode(item.getOrderno());
                    info.setBillType("order");
                    info.setNum(0);
                }
                info.setNum(info.getNum()+pickNum);
                this.outstorageInfoService.save(info);
            } //  end for of WorkItems
            Date now =new Date();
            msg="task_finishing";
            //task.setStatus("3"); //任务状态( 1.创建任务 2.已分配拣货任务  3.已拣货  4. 已分配灯光拣选任务  5.已经灯光拣选  6.已分配包装任务  7.已包装  8.已分配发货任务  9.已发货  10.灯光拣选进行中.. 11.推车拣选进行中..)
            //this.workTaskDao.save(task);
            workTaskDao.updateTaskStatusForPick(totelPickNum,"3",task.getTaskCode());
            User user=this.userDao.findOne(task.getPickerId());
            //作业日志
            WorkLog workLog=new WorkLog(
                    task.getBatchCode(),
                    "4", //操作类型 (1.创建批次 2.创建任务 3.领取拣货任务  4.完成拣货任务 5.领取灯光拣选任务 6.完成灯光拣选任务  7.领取包装任务 8完成包装任务  9.领取发货任务  10.完成发货任务  11.打印单据 )
                    "完成快速拣货任务("+taskCode+")",
                    now,
                    user);
            this.workLogDao.save(workLog);
            
           //修改订单状态，添加日志
           List<WorkOrder> orderList=this.workOrderDao.loadOrderByTaskCode(taskCode);
           List<OrderLog> orderLogList=new ArrayList<OrderLog>();
           for (WorkOrder order : orderList) {
               if("lamp".equals(task.getPickModel())){  //灯光拣选订单 
                  workOrderDao.updateStatusByOrder("3",order.getId()); //订单状态 (1.创建批次 2.创建任务 3.已拣货 4.已灯光拣选 9.待包装 5.已包装 6.已发货 7.已签收 8.异常 )
              }else{
                  workOrderDao.updateStatusByOrder("9",order.getId()); //订单状态 (1.创建批次 2.创建任务 3.已拣货 4.已灯光拣选 9.待包装 5.已包装 6.已发货 7.已签收 8.异常 )
              }
              OrderLog log=new OrderLog(order.getOrder().getOrdeno(), order.getCustomerCode(), "3", user, now, null, user.getRealname()+"完成拣货");
              orderLogList.add(log);
              //SynchroShippedBatchQueue.putSendMessageQueue("warehouseInfo"+StatusEnums.split.getStatus()+order.getOrder().getOrdeno()+ "_jianhuo");
           }
           this.orderLogDao.save(orderLogList);
           
           //查看同一批次的其他任务是否完成，如果都完成，修改入库批次状态为：3
           List<WorkTaskItem> uncompletedTaskList=workTaskItemDao.loadUnPickItemByBatchCode(task.getBatchCode());
           if(uncompletedTaskList!=null && uncompletedTaskList.size()==0){
                WorkBatch batch=this.workBatchDao.loadbatchByBatchCode(task.getBatchCode());
                batch.setStatus("3"); //批次状态 (1.已创建批次 2.已创建任务 3.已拣货  4.已包装  5.已发货)
                this.workBatchDao.save(batch);
                
                //添加工作日志
                WorkLog workLog1=new WorkLog(
                        task.getBatchCode(),
                        "4",//操作类型 (1.创建批次 2.创建任务 3.领取拣货任务  4.完成拣货任务 5.领取灯光拣选任务 6.完成灯光拣选任务  7.领取包装任务 8完成包装任务  9.领取发货任务  10.完成发货任务   )
                        "拣货任务全部完成", 
                        now, 
                        null);
                this.workLogDao.save(workLog1);
            }
           
           /** begin add 20160621 写接口任务表，job处理 by lianghe.yuan */
           sendQMInfo(orderList);
           /** end add 20160621 写接口任务表，job处理 by lianghe.yuan */
           
           /** begin remove 20160621 采用异步处理 by lianghe.yuan */
           /*for(WorkOrder wo:orderList){
                try{
                    log.info("-----发送奇门出库单流水信息 已推车拣货 orderno "+wo.getOrder().getOrdeno());
                    Map<String,Object> params = new HashMap<String,Object>();
                    EdiOrder ediOrder = wo.getOrder();
                    params.put("ediOrder", ediOrder);
                    params.put("status", "pick");
                    deliveryProcessService.send(params,ediOrder.getCustomerCode());
                    log.info("-----发送奇门出库单流水信息发送完毕 已推车拣货 end");
                }catch(Exception e){
                    log.info("-----发送奇门出库单流水信息发送异常 已推车拣货 error");
                }
            }*/
           /** end remove 20160621 采用异步处理 by lianghe.yuan */

           //modify 20160921 放到最后 bug:525
            for (WorkTaskItem item : items) {
                int processNum = item.getNum() - item.getPickedNum();
                updateStock(item, processNum);
            }
            return msg;
        
        } catch (Exception e) {
            log.error("pick error. taskCode = {}", taskCode, e);
            throw e;
        }
        
    }
    
    
    /**
     * 
     * @param taskItemId 拣货任务项ID
     * @param sku  sku编码
     * @return 'coutinue'       : 拣货成功,继续此任务项拣货
     *         'finished'       : 此任务项已完成
     *         'finishing'      : 拣货成功,此任务项完成
     *         'task_finishing' : 拣货成功,此任务已经完成
     *         'error'          : 验证不通过
     * @throws Exception 
     */
    @Transactional(readOnly = false,rollbackFor=Exception.class)
    public String  pick(Long taskItemId, String sku) throws Exception {
            return pick(taskItemId,sku,1);
    }
    /**
     * 
     * @param taskItemId 拣货任务项ID
     * @param sku  sku编码
     * @param pickNum 拣货的数量
     * @return 'coutinue'       : 拣货成功,继续此任务项拣货
     *         'finished'       : 此任务项已完成
     *         'finishing'      : 拣货成功,此任务项完成
     *         'task_finishing' : 拣货成功,此任务已经完成
     *         'error'          : 验证不通过
     * @throws Exception 
     */
    @Transactional(readOnly = false,rollbackFor=Exception.class)
    public String  pick(Long taskItemId, String sku,int pickNum) throws Exception {
        try {
            //参数验证
            if(pickNum <= 0)
                return "error";
            
            //根据taskItemId获取对应拣货项
            WorkTaskItem item=this.workTaskItemDao.findOne(taskItemId);
            
            //拣货项级别验证
            if(item == null || !item.getSku().toUpperCase().equals(sku.toUpperCase()))
                return "error";
            
            if(item.getPickStatus().equals("picked"))
                return "finished";
            
            String msg="error";
            WorkTask task = workTaskDao.loadTaskByTaskCode(item.getTaskCode());
            
            //对比拣货项上的数量与拣货数量
            if(item.getNum() > item.getPickedNum() + pickNum){
                msg = "continue";
                task.setPickedNum(task.getPickedNum() + pickNum);
            }else if(item.getNum() == item.getPickedNum() + pickNum){
                msg="finishing";
                task.setPickedNum(task.getPickedNum()+pickNum);
            }else{
                return msg;
            }
            this.workTaskDao.save(task);
            
            //写入出库日志
            outStorageLog(item, sku, pickNum);
            
            //更新拣货行
            int cnt = updateTaskItemForPickNew(pickNum, item.getNum() - (item.getPickedNum() + pickNum)==0 ? "picked" : "picking", 
                                               item.getVersion(), item.getId());
            if (cnt == 0) {
                throw new RuntimeException("任务数据已过期或者超出任务明细的剩余待拣货数量！本次提交数量：" + pickNum + ", work_task_item.id: " 
                                        + taskItemId);
            }
            
            //拣货任务完成
            if(msg == "finishing")
            {
                msg = finishPick(task);
                
            }
            
            //扣减库存
            //modify 20160921 放到最后 bug:525
            updateStock(item, pickNum);
            
            return msg;
        
        } catch (Exception e) {
            log.error("pick error :taskItemId = "+taskItemId+" sku = "+ sku+" pickNum = "+pickNum ,e);
            throw e;
        }
        
    }
    
    /**
     * 拣货_优化方法 by ch 20140402
     * @param taskItemId 拣货任务项ID
     * @param sku  sku编码
     * @param boxCode  库位箱编码
     * @return 'error_itemnull'  : 无此任务项
     *         'error_sku'       : sku码错误 
     *         'error_boxCode'   : 库位箱编码错误 
     *         'error_finished'  : 此任务项已经完成
     *         'item_finishing'  : 拣货成功,继续下一个任务项
     *         'task_finishing'  : 拣货成功,此任务已经完成
     *         'error'           : 验证不通过
     * @throws Exception 
     */
    @Transactional(readOnly = false,rollbackFor=Exception.class)
    public String  pick(Long taskItemId,String sku,String boxCode) throws Exception {
        try {
            WorkTaskItem item=this.workTaskItemDao.findOne(taskItemId);
            String msg="error";
            
            //拣货项级别验证
            if(item==null){
                return "error_itemnull"; //无此任务项
            }
            
            if(!item.getBoxCode().equals(boxCode)){
                return "error_boxCode"; //库位箱编码错误 
            }
            
            if(!item.getSku().equals(sku)){
                return "error_sku"; //sku码错误 
            }
            
            if(item.getPickStatus().equals("picked")){ //任务项已经完成
                return "error_finished";
            }
            
            if (item.getPickedNum() > 0) {
                return "error";
            }
            item.setPickedNum(item.getNum());
            item.setPickStatus("picked");
            msg="item_finishing"; //拣货成功,此任务项完成
            this.workTaskItemDao.save(item);
            
            //写入出库日志
            outStorageLog(item, sku, item.getNum());
            
            //完成拣货任务
            WorkTask task=this.workTaskDao.loadTaskByTaskCode(item.getTaskCode());
            task.setPickedNum(task.getPickedNum() + item.getNum());
            msg = finishPick(task); 
            if(msg == "finishing")
                msg = "item_finishing";
            
            //更新库存
            //modify 20160921 放到最后 bug:525
            updateStock(item, item.getNum());
            
            return msg;
        
        } catch (Exception e) {
            log.error("error  taskItemId = "+taskItemId+", sku = "+sku+",boxCode = "+boxCode, e);
            throw e;
        }
        
    }
    
    /**
     * 一键完成推车拣选
     */
    @Transactional(readOnly = false,rollbackFor=Exception.class)
    public String  pick(Long taskId) throws Exception { 
        
        WorkTask task=this.workTaskDao.findOne(taskId);
        if("3".equals(task.getStatus())){
            return "error_status";
        }
        
        User user=this.userDao.findOne(task.getPickerId());
        List<WorkTaskItem> items=workTaskItemDao.findByTaskCode(task.getTaskCode());
        for (WorkTaskItem workTaskItem : items) {
            if (workTaskItem.getPickedNum() > 0) {
                throw new RuntimeException("一键拣货，但是存在已拣货数量大于0的任务明细。订单号：" + workTaskItem.getOrderno());
            }
            
            //修改拣货任务明细的数量和状态
            log.info("一键完成推车拣选-->修改拣货任务明细的数量和状态:"+workTaskItem.getTaskCode());
            updateWTItemStatueAndNum(workTaskItem);
            
            //修改库存状态：从订单占用状态减去
            //modify 20160921 放到最后 bug:525
            //log.info("一键完成推车拣选-->修改库存状态");
            //updateStock(workTaskItem,workTaskItem.getNum());
            
            //拣货成功，写入出库信息
            outStorageLog(workTaskItem, workTaskItem.getSku(), workTaskItem.getNum());
        }
        //修改拣货任务的数量和状态
        task.setPickedNum(task.getGoodsNum());
        task.setStatus("3");
        workTaskDao.save(task);
        //作业日志
        addWorkLogByBatch(task, user);
        //修改订单状态，添加日志
        updateOrderStateAndAddLog(task,user);
        //释放流转箱
        log.info("一键完成推车拣选-->释放流转箱"+task.getBoxCode());
        freeBox(task);
        if(null!=task.getPickcarId())freeCar(task.getPickcarId());
        //查看同一批次的其他任务是否完成，如果都完成，修改入库批次状态为：3
        updateSameBatchState(task);
        
        //modify 20160921 更新库存放到最后 bug:525
        for (WorkTaskItem workTaskItem : items) {
            //修改库存状态：从订单占用状态减去
            log.info("一键完成推车拣选-->修改库存状态. workTaskItem.id:{}", workTaskItem.getId());
            updateStock(workTaskItem, workTaskItem.getNum());
        }
        
        return "task_finished";
    }
    
    
    /**
     * 拣货后扣减库存
     * 
     *
     * @param 
     * @return 
     * @throws 
     * @author Administrator
     * @version 1.0.0
     */
    protected void updateStock(WorkTaskItem item, int pickNum) {
        String _customerCode = item.getCustomerCode();
        String _warehouseCode = item.getWarehouseCode();
        String _stockCode = item.getStockCode();
        String _boxCode = item.getBoxCode();
        String _sku = item.getSku();
        /*CusStock _stock=this.cusStockDao.loadStock(_customerCode, _warehouseCode, _stockCode, _boxCode, _sku);
        if( _stock.getOrderNum() - pickNum < 0){//update by LiBin 20160808 原来是_stock.getOrderNum()<=0
            throw new Exception("订单占用库存异常：订单号："+item.getOrderno()+" sku:"+ item.getSku());
        }
        _stock.setOrderNum(_stock.getOrderNum()-pickNum);  
        this.cusStockDao.save(_stock);*/
        
        /** modify 20160921 bug:525 */
        int cnt = cusStockDao.updateCusStock4Pick(_customerCode, _warehouseCode, _stockCode, _boxCode, _sku, pickNum, 1);
        if (cnt == 0) {
            throw new RuntimeException("订单占用库存扣减异常：订单号："+item.getOrderno()+" sku:"+ item.getSku());
        }
    }
    
    
    /**
     * 写入出库日志
     * 
     *
     * @param 
     * @return 
     * @throws 
     * @author Administrator
     * @version 1.0.0
     */
    protected void outStorageLog(WorkTaskItem item, String sku, int pickNum) throws Exception{
        OutstorageInfo info=this.outstorageInfoService.loadByTaskCode(item.getTaskCode(),sku);
        if(info==null){
            info=new OutstorageInfo();
            info.setCustomerCode(item.getCustomerCode());
            info.setWarehouseCode(item.getWarehouseCode());
            info.setBatchCode(item.getBatchCode());
            info.setTaskCode(item.getTaskCode());
            info.setSku(item.getSku());
            info.setOpeTime(getNow());
            info.setAboutCode(item.getOrderno());
            info.setBillType("order");
            info.setNum(0);
        }
        info.setNum(info.getNum()+pickNum);
        this.outstorageInfoService.save(info);
    }
    
    /**
     * 拣货任务完成
     * 
     *
     * @param 
     * @return 
     * @throws 
     * @author Administrator
     * @version 1.0.0
     */
    protected String finishPick(WorkTask task) throws Exception{
            String msg = "finishing";
            List<WorkTaskItem> allItem=this.workTaskItemDao.loadUnPickItemByTaskCode(task.getTaskCode());
            if(allItem!=null && allItem.size()==0){
                task.setStatus("3"); //任务状态( 1.创建任务 2.已分配拣货任务  3.已拣货  4. 已分配灯光拣选任务  5.已经灯光拣选  6.已分配包装任务  7.已包装  8.已分配发货任务  9.已发货  10.灯光拣选进行中.. 11.推车拣选进行中..)
                this.workTaskDao.save(task);
                
                User user=this.userDao.findOne(task.getPickerId());
                
                workLog(task.getBatchCode(), "4", "完成拣货任务(" + task.getTaskCode() + ")", getNow(), user);
                
                orderLog(task, user);
                
                //freeBox(task);
                
                List<WorkTaskItem> uncompletedTaskList=workTaskItemDao.loadUnPickItemByBatchCode(task.getBatchCode());
                
                if(uncompletedTaskList!=null && uncompletedTaskList.size()==0)
                    batchLog(task);
               
                workLog(task.getBatchCode(), "4", "拣货任务全部完成", getNow(), null);
               
                msg = "task_finishing";
            }else {
                log.info("remain item: " + allItem.size() +" not completed.");
            }
            return msg;
    }
    
    /**
     * 作业日志
     * 
     *
     * @param 
     * @return 
     * @throws 
     * @author Administrator
     * @version 1.0.0
     */
    protected void workLog(String batchCode,String workType, String info, Date workTime, User work){
        WorkLog workLog=new WorkLog(batchCode, workType, info, workTime, work);
        this.workLogDao.save(workLog);
    }
    
    /**
     * 订单日志并发送奇门接口
     * 
     *
     * @param 
     * @return 
     * @throws 
     * @author Administrator
     * @version 1.0.0
     */
    protected void orderLog(WorkTask task, User user){
        List<WorkOrder> orderList=this.workOrderDao.loadOrderByTaskCode(task.getTaskCode());
        List<OrderLog> orderLogList=new ArrayList<OrderLog>();
        for (WorkOrder order : orderList) {
            if("lamp".equals(task.getPickModel())){  //灯光拣选订单 
               workOrderDao.updateStatusByOrder("3",order.getId()); //订单状态 (1.创建批次 2.创建任务 3.已拣货 4.已灯光拣选 9.待包装 5.已包装 6.已发货 7.已签收 8.异常 )
           }else{
               workOrderDao.updateStatusByOrder("9",order.getId()); //订单状态 (1.创建批次 2.创建任务 3.已拣货 4.已灯光拣选 9.待包装 5.已包装 6.已发货 7.已签收 8.异常 )
           }
           OrderLog log=new OrderLog(order.getOrder().getOrdeno(), order.getCustomerCode(), "3", user, getNow(), null, user.getRealname()+"完成拣货");
           orderLogList.add(log);
           //SynchroShippedBatchQueue.putSendMessageQueue("warehouseInfo"+StatusEnums.split.getStatus()+order.getOrder().getOrdeno()+ "_jianhuo");
        }
        this.orderLogDao.save(orderLogList);
        sendQMInfo(orderList);
    }
    
    /**
     * 修改批次信息并写入日志
     *
     * @param 
     * @return 
     * @throws 
     * @author Administrator
     * @version 1.0.0
     */
    protected void batchLog(WorkTask task){
        WorkBatch batch=this.workBatchDao.loadbatchByBatchCode(task.getBatchCode());
        batch.setStatus("3"); //批次状态 (1.已创建批次 2.已创建任务 3.已拣货  4.已包装  5.已发货)
        this.workBatchDao.save(batch);
    }
    
    

    /**
     * 绑定流转箱
     * @param taskCode
     * @param workBoxCode
     * @return success:绑定成功  busy:流转箱被占用   error:流转箱条码异常
     * @throws Exception 
     */
    @Transactional(readOnly = false,rollbackFor=Exception.class)
    public String bindBox(String taskCode, String workBoxCode) throws Exception {
            WorkTask task=this.workTaskDao.loadTaskByTaskCode(taskCode);
            WorkBox box=this.workBoxDao.loadByBoxCode(workBoxCode,task.getWarehouseCode());
            
            if(box==null){
                return "error"; //盒子不存在
            }
            
            if("busy".equals(box.getStatus()) ){ 
                return "busy"; //箱子被占用
            }else{
                
                //修改流转箱状态
                box.setStatus("busy");
                box.setTaskCode(taskCode);
                this.workBoxDao.save(box);
                
                //修改任务状态
                String status = task.getStatus().equals("2") ? "12" : task.getStatus();
                workTaskDao.updateBoxCode(workBoxCode, status, taskCode);
                return "success"; //绑定成功
            }
    }
    /**
     * 拣货绑定箱子_app
     * @param workBoxCode
     * @param taskCode
     * @param jobuuid
     * @return token:任务已经被领取    error:流转箱不存在   busy:流转箱被占用    success:绑定成功
     */
    @Transactional(readOnly = false,rollbackFor=Exception.class)
    public String bindBox_app(String workBoxCode, String taskCode,String jobuuid) throws Exception {
            
            WorkTask task=this.loadTaskByCode(taskCode);
            WorkBox box=this.workBoxDao.loadByBoxCode(workBoxCode,task.getWarehouseCode());
            User curUser=this.userDao.findByJobuuid(jobuuid);
            
            if ("1".equals(task.getFastFlag())) {
                return "fast"; //已经被快捷领取
            }
            
            if(box==null){
                return "error"; //流转箱不存在
            }
            
            if("busy".equals(box.getStatus()) ){ 
                return "busy"; //流转箱被占用
            }
            
            //领取任务
            if(!task.getStatus().equals("1")){ 
                User _user=this.userDao.findOne(task.getPickerId());
                String _jobuuid=_user.getJobuuid();
                if(jobuuid.equals(_jobuuid)){
                    return "tokenByself"; //任务被自己领取
                }else{
                    return "token"; //任务已经别人被领取
                }
                
            }else{
                this.takeTask(task.getId(),curUser.getId(),"pick");
                task.setStatus("12"); //任务状态:开始拣货任务
                task.setBoxCode(workBoxCode);
                this.workTaskDao.save(task);
            }
            
            //绑定流转箱
            box.setStatus("busy");
            box.setTaskCode(taskCode);
            this.workBoxDao.save(box);
            
            return "success"; //绑定成功

        
    }
    
    /**
     * 拣货绑定箱子_app
     * @param workBoxCode
     * @param taskCode
     * @param jobuuid
     * @return token:任务已经被领取    error:流转箱不存在   busy:流转箱被占用    success:绑定成功
     */
    @Transactional(readOnly = false,rollbackFor=Exception.class)
    public String bindBox_app2(String workBoxCode, String taskCode,String jobuuid) throws Exception {
            
            WorkTask task=this.loadTaskByCode(taskCode);
            WorkBox box=this.workBoxDao.loadByBoxCode(workBoxCode,task.getWarehouseCode());
            User curUser=this.userDao.findByJobuuid(jobuuid);
            
            if ("1".equals(task.getFastFlag())) {
                return "fast"; //已经被快捷领取
            }
            
            if(box==null){
                return "error"; //流转箱不存在
            }
            
            if("busy".equals(box.getStatus()) ){ 
                return "busy"; //流转箱被占用
            }
            
            //领取任务
            if(!task.getStatus().equals("1")){ 
                User _user=this.userDao.findOne(task.getPickerId());
                String _jobuuid=_user.getJobuuid();
                if(jobuuid.equals(_jobuuid)){
                    if(null == task.getBoxCode() || "".equals(task.getBoxCode()))
                    {
                        //this.takeTask(task.getId(),curUser.getId(),"pick");
                        task.setStatus("12"); //任务状态:开始拣货任务
                        task.setBoxCode(workBoxCode);
                        this.workTaskDao.save(task);
                    }
                    else
                    {
                        return "tokenByself"; //任务被自己领取
                    }
                    
                }else{
                    return "token"; //任务已经别人被领取
                }
                
            }else{
                this.takeTask(task.getId(),curUser.getId(),"pick");
                task.setStatus("12"); //任务状态:开始拣货任务
                task.setBoxCode(workBoxCode);
                this.workTaskDao.save(task);
            }
            
            //绑定流转箱
            box.setStatus("busy");
            box.setTaskCode(taskCode);
            this.workBoxDao.save(box);
            
            return "success"; //绑定成功

        
    }
    
    @Resource(type = OrderOutofstockService.class)  
    QmRequestSender<EdiOrder> qmRequestSender;
    /**
     * @param orderno
     * @return
     */
    @Transactional(readOnly = false,rollbackFor=Exception.class)
    public String backUnhandleOrder(String orderno)  throws Exception{
        
        EdiOrder ediOrder = this.ediOrderService.findByOrdeno(orderno);
        if(ediOrder==null){
            throw new PaiUException(ErrorCode.CANCEL_NO_EXIST);
        }else if("pending".equals(ediOrder.getStatus())) {
            throw new PaiUException(ErrorCode.CANCEL_BACK);
        }
        
        WorkOrder workOrder = this.workOrderDao.findByOrder(orderno);
        if(workOrder == null){
            throw new PaiUException(ErrorCode.CANCEL_NO_EXIST);
        }
        /*String stockInfo = workOrder.getStockInfo() ;
        String customerCode = workOrder.getCustomerCode() ;
        String warehouseCode = workOrder.getWarehouseCode();
        String ordeno = workOrder.getOrder().getOrdeno() ;*/
        //删除已生成批次的订单
        this.workOrderDao.delete(workOrder);
        if(workOrder.getBatchCode() == null|| workOrder.getBatchCode().equals("")){
            throw new PaiUException(ErrorCode.CANCEL_BACK);
        }
        // 修改订单数量
        WorkBatch wb = this.workBatchService.loadWorkBatchByCode(workOrder.getBatchCode());
        wb.setOrderQty(wb.getOrderQty()-1);
        if(wb.getOrderQty()<=0){
            workBatchDao.delete(wb);
        }else{
            workBatchDao.save(wb);
        }
            
        // 修改edi_order状态为 status = pending
        ediOrder.setStatus("pending");
        
        //修改优先派送标志,改为0
        ediOrder.setPrioritySendFlag("0");
        
        ediOrderService.save(ediOrder);
        
        
        /**
         * 修改可处理状态为否  dispatch=0
         */
        ediOrderService.updateEdiOrderDispatchFlagByOrdeno(orderno);
        /**
         * 修改merge表数据
         */
        /*String[] infoArray = stockInfo.split(";");
        for (String info : infoArray) {
            String[] _arr = info.split("_");
            String stockCode = _arr[0];
            String boxCode = _arr[1];
            String sku = _arr[2];
            Integer num = Integer.valueOf(_arr[3]+"");
            CusStockMerge merge=this.cusStockMergeService.findCustomerWarSku(customerCode, warehouseCode, sku);
            if(merge!=null){
                int _orderNum=merge.getOrderNum();
                int temp=_orderNum-num;
                if (temp < 0) {
                    log.error("预定库存异常，sku:"+sku+" ; 商家："+customerCode+" ; 仓库："+warehouseCode);
                }
                merge.setOrderNum(Math.max(temp,0));
                this.cusStockMergeService.save(merge);
            }
        }*/
        // delete by yuansheng
        /*try{
            //调用缺货通知接口
            qmRequestSender.send(ediOrder,ediOrder.getCustomerCode());
        }catch(Exception e) {
//            throw new PaiUException(ErrorCode.DATA_ERROR); 
            log.error("---奇门 调用缺货通知接口 error",e);
        }*/
        // delete by yuansheng
        return "success";
    }
    
    
    /**
     * 检查该任务是否已打印面单
     * @param task 当前任务
     * @return true 其中一个未打印
     */
    private boolean checkIsPrinted(WorkTask task) {
        
        List<WorkOrder> orderList=this.workOrderDao.loadOrderByTaskCode(task.getTaskCode());
        for (WorkOrder order : orderList) {
            if (order.getPrintFlag()<1) {
                return true;
            }
        }
        return false;
    }

    /**
     * 修改拣货任务明细的数量和状态
     * @param workTaskItem
     */
    private void updateWTItemStatueAndNum(WorkTaskItem workTaskItem) {
        workTaskItem.setPickedNum(workTaskItem.getNum());
        workTaskItem.setPickStatus("picked");
        workTaskItemDao.save(workTaskItem);
    }

    /**
     * 修改库存状态：从订单占用状态减去
     * @param pickNum 拣货数量
     * @param item 拣货明细
     * @throws Exception
     */
    private void updateStock(int pickNum, WorkTaskItem item) throws Exception {
        CusStock _stock=this.cusStockDao.loadStock(item.getCustomerCode(), item.getWarehouseCode(), item.getStockCode(), item.getBoxCode(), item.getSku());
        if(_stock.getOrderNum() - pickNum < 0){//update by LiBin 20160808 原来是_stock.getOrderNum()<=0
            throw new Exception("订单占用库存异常：订单号："+item.getOrderno()+" sku:"+item.getSku());
        }
        _stock.setOrderNum(_stock.getOrderNum()-pickNum);
        this.cusStockDao.save(_stock);
    }
    /**
     * 拣货成功，写入出库信息
     * @param pickNum 拣货数量
     * @param item 任务明细
     * @param task 任务
     */
    private void saveOutstorageInfo(int pickNum, WorkTaskItem item,
            WorkTask task,String sku) {
        OutstorageInfo info=this.outstorageInfoService.loadByTaskCode(item.getTaskCode(),sku);
        if(info==null){
            info=new OutstorageInfo();
            info.setCustomerCode(item.getCustomerCode());
            info.setWarehouseCode(item.getWarehouseCode());
            info.setBatchCode(item.getBatchCode());
            info.setTaskCode(item.getTaskCode());
            info.setSku(item.getSku());
            info.setOpeTime(task.getCreateTime());
            info.setAboutCode(item.getOrderno());
            info.setBillType("order");
            info.setNum(0);
        }
        info.setNum(info.getNum()+pickNum);
        this.outstorageInfoService.save(info);
    }
    
    
    /**
     * 根据 作业批次号增加 作业日志
     * @param item 任务明细
     * @param now
     * @param user
     */
    private void addWorkLogByBatch(WorkTask task, User user) {
        WorkLog workLog=new WorkLog(
                task.getBatchCode(),
                "4", //操作类型 (1.创建批次 2.创建任务 3.领取拣货任务  4.完成拣货任务 5.领取灯光拣选任务 6.完成灯光拣选任务  7.领取包装任务 8完成包装任务  9.领取发货任务  10.完成发货任务  11.打印单据 )
                "完成拣货任务("+task.getTaskCode()+")",
                getNow(),
                user);
        this.workLogDao.save(workLog);
    }
    
    /**
     * 修改订单状态，添加日志
     * @param taskCode 任务号
     * @param task 任务
     * @param user
     */
    private void updateOrderStateAndAddLog(WorkTask task, User user) {
           List<WorkOrder> orderList=this.workOrderDao.loadOrderByTaskCode(task.getTaskCode());
           List<OrderLog> orderLogList=new ArrayList<OrderLog>();
           for (WorkOrder order : orderList) {
               if("lamp".equals(task.getPickModel())){  //灯光拣选订单 
                  workOrderDao.updateStatusByOrder("3",order.getId()); //订单状态 (1.创建批次 2.创建任务 3.已拣货 4.已灯光拣选 9.待包装 5.已包装 6.已发货 7.已签收 8.异常 )
              }else{
                  workOrderDao.updateStatusByOrder("9",order.getId()); //订单状态 (1.创建批次 2.创建任务 3.已拣货 4.已灯光拣选 9.待包装 5.已包装 6.已发货 7.已签收 8.异常 )
              }
              OrderLog log=new OrderLog(order.getOrder().getOrdeno(), order.getCustomerCode(), "3", user, getNow(), null, user.getRealname()+"完成拣货");
              orderLogList.add(log);
              //SynchroShippedBatchQueue.putSendMessageQueue("warehouseInfo"+StatusEnums.split.getStatus()+order.getOrder().getOrdeno()+ "_jianhuo");
           }
           this.orderLogDao.save(orderLogList);
           //结果 发至奇门
           sendQMInfo(orderList);
    }
    
    
    /**
     * 结果 发至奇门
     * @param orderList
     */
    private void sendQMInfo(List<WorkOrder> orderList) {
        for(WorkOrder wo:orderList){
                
            /** begin add 20160621 写接口任务表，job处理 by lianghe.yuan */
             InterfaceTask interfaceTask = new InterfaceTask();
             interfaceTask.setType(InterfaceTaskEnum.TYPE_QM_DELIVERY_PICK);
             interfaceTask.setRelatedNo(wo.getOrder().getOrdeno());
             interfaceTask.setRelatedId(wo.getOrder().getId());
             interfaceTask.setCreatedTime(new Date());
             interfaceTaskService.saveTask(interfaceTask);
             /** end add 20160621 写接口任务表，job处理 by lianghe.yuan */
             
             /** begin remove 20160621 采用异步处理 by lianghe.yuan */
            /*try{
                log.info("-----发送奇门出库单流水信息 已推车拣货 orderno "+wo.getOrder().getOrdeno());
                Map<String,Object> params = new HashMap<String,Object>();
                EdiOrder ediOrder = wo.getOrder();
                params.put("ediOrder", ediOrder);
                params.put("status", "pick");
                deliveryProcessService.send(params,ediOrder.getCustomerCode());
                log.info("-----发送奇门出库单流水信息发送完毕 已推车拣货 end");
            }catch(Exception e){
                log.info("-----发送奇门出库单流水信息发送异常 已推车拣货 error");
            }*/
             /** end remove 20160621 采用异步处理 by lianghe.yuan */
        }
    }
    
    /**
     * 获取当前日期
     * @return
     */
    private Date getNow() {
        Date now=new Date();
        return now;
    }
    
    /**
     * 查看同一批次的其他任务是否完成，如果都完成，修改入库批次状态为：3
     * @param task 当前任务
     * @param now 日期
     */
    private void updateSameBatchState(WorkTask task) {
           List<WorkTaskItem> uncompletedTaskList=workTaskItemDao.loadUnPickItemByBatchCode(task.getBatchCode());
           if(uncompletedTaskList!=null && uncompletedTaskList.size()==0){
                WorkBatch batch=this.workBatchDao.loadbatchByBatchCode(task.getBatchCode());
                batch.setStatus("3"); //批次状态 (1.已创建批次 2.已创建任务 3.已拣货  4.已包装  5.已发货)
                this.workBatchDao.save(batch);
                //添加工作日志
                addWorkLogFor4(task);
            }
    }
    
    /**
     * 针对拣货任务全部完成,增加工作日志
     * @param task
     */
    private void addWorkLogFor4(WorkTask task) {
        WorkLog workLog1=new WorkLog(
                task.getBatchCode(),
                "4",//操作类型 (1.创建批次 2.创建任务 3.领取拣货任务  4.完成拣货任务 5.领取灯光拣选任务 6.完成灯光拣选任务  7.领取包装任务 8完成包装任务  9.领取发货任务  10.完成发货任务   )
                "拣货任务全部完成", 
                getNow(), 
                null);
        this.workLogDao.save(workLog1);
    }
    
    /**
     * 释放流转箱
     * @param task 当前任务
     */
    private void freeBox(WorkTask task) {
        String boxCode=task.getBoxCode();
        if(StringUtils.isNotBlank(boxCode)){
            WorkBox box=this.workBoxDao.loadByBoxCode(boxCode, task.getWarehouseCode());
            if(box != null){
            box.setStatus("free");
            box.setTaskCode(null);
            this.workBoxDao.save(box);
            }
        }
    }
    
    /**
     * 释放推荐车
     * @param task 当前任务
     */
    private void freeCar(Long pickcarId) throws Exception {
        pickCarService.free(pickcarId);
    }
    
    @Transactional(readOnly = false,rollbackFor=Exception.class)
    public void updatePickInfo(String taskCode){
        workTaskDao.updatePickInfoStatus("yes", taskCode);
    }
    
    @Transactional(readOnly = false,rollbackFor=Exception.class)
    public void updateTaskPrintFlag(String taskCode,int printFlag){
        workTaskDao.updateTaskPrintFlag(taskCode,printFlag);
    }
    
    @Transactional(readOnly=true)
    public List<WorkTaskItem> loadWorkTaskItem(String taskCode){
        return workTaskItemDao.loadByTaskCode(taskCode);
    }
    @Transactional(readOnly=true)
    public List<WorkOrder> loadWorkOrderLike(String taskCode,String stockInfo){
        String stocksInfo=new StringBuilder().append("%").append(stockInfo).append("%").toString();
        return workOrderDao.loadWorkOrderLike(taskCode, stocksInfo);
    }
    @Transactional(readOnly = false,rollbackFor=Exception.class)
    public void saveWorkTask(WorkTask workTask){
        workTaskDao.save(workTask);
    }
    
    
    /**
     * bug:357。 同一个数据操作锁定，
     * 解决重复操作问题（同一个时间段内多次触发提交）。add 20160618 lianghe.yuan
     * 
     * @param methodName 对应的方法名称
     * @param relatedCode 相关编号/单号
     * @param operator 操作人姓名
     * @return lock success if return true, otherwise fail.
     */
    public boolean lock(String methodName, String relatedCode, String operator) {
        try {
            return lockMain(methodName, relatedCode, operator);
        } catch (Exception ex) {
            return false;
        }
    }
    
    @Transactional
    public boolean lockMain(String methodName, String relatedCode, String operator) {
        String sql = "INSERT INTO operate_lock(method_name, related_code, operator, operated_time) "
                + " SELECT ?, ?, ?, ? FROM DUAL "
                + " WHERE NOT EXISTS (SELECT 1 FROM operate_lock WHERE method_name=? and related_code=?)";
        
        Query query = em.createNativeQuery(sql);
        
        int i = 1;
        query.setParameter(i++, methodName);
        query.setParameter(i++, relatedCode);
        query.setParameter(i++, operator);
        query.setParameter(i++, new Date());
        query.setParameter(i++, methodName);
        query.setParameter(i++, relatedCode);
        
        int count = query.executeUpdate();
        
        return count == 1 ? true : false;
    }
    
    /**
     * bug:357。
     * 释放锁。add 20160618 lianghe.yuan
     * 
     * @param methodName 对应的方法名称
     * @param relatedCode 相关编号/单号
     */
    @Transactional
    public void releaseLock(String methodName, String relatedCode) {
        String sql = "DELETE FROM operate_lock WHERE method_name=? and related_code=?";
        
        Query query = em.createNativeQuery(sql);
        
        int i = 1;
        query.setParameter(i++, methodName);
        query.setParameter(i++, relatedCode);
        
        query.executeUpdate();
    }
    
    
    //WorkTaskItemDao#updateTaskItemForPickNew  返回始终0
    //add 20160622
    public int updateTaskItemForPickNew(int pickNum, String status, int version, long taskItemId) {
        String sql = "update work_task_item set picked_num=picked_num + ?, pick_status=? , version = version + ? where id=?  and version=? and num >= (picked_num + ?)";
        Query query = em.createNativeQuery(sql);
        
        int i = 1;
        query.setParameter(i++, pickNum);
        query.setParameter(i++, status);
        query.setParameter(i++, 1);
        query.setParameter(i++, taskItemId);
        query.setParameter(i++, version);
        query.setParameter(i++, pickNum);
        
        return query.executeUpdate();
    }
    
    /**
     * 根据订单号查询作业任务
     * 
     *
     * @param orders
     * @return [参数说明]
     * @author <a href=mailto:zhangweize@nryuncang.com>zhangweize</a>
     * @version 1.0.0
     */
    public List<String> findTaskCodeByOrders (List<String> ordersList){
    	String sql="select DISTINCT(a.task_code) as task_code  from work_task a ,work_order b where a.task_code =b.task_code  and b.orderno in (?1)";
    	Query query = em.createNativeQuery(sql);
    	query.setParameter(1, ordersList);
    	return  query.getResultList();
    }
    
}